数据结构之使用双向链表或数组实现环形队列

数据结构之使用双向链表或数组实现环形队列,第1张

数据结构之使用双向链表或数组实现环形队列 1. 环形队列分析

环形队列是一种复用性极高的数据结构,被使用在许多场景中,如在MySQL数据库的InnoDB存储引擎中的Redo log日志,在DB挂了的时候,提供即使的数据恢复,保证了其持久性。默认便是有四个文件循环写入修改信息。又例如Disruptor消息队列,其任务队列便是一个环形队列,循环写入,写满即覆盖继续写。

逻辑图如下:

环形队列的一个主要特性便是当队列满了之后,回到头部继续push,这里可采用两个指针pushPoint和popPoint进行实现。分析图如下。

2. 代码实现

双向链表实现环形队列

public class Ringlinked {
    public static void main(String[] args) {
        Ringlinked buffer = new Ringlinked(4);
        buffer.push(1);
        buffer.push(2);
        buffer.push(3);
        buffer.push(4);
        System.out.println(buffer.pop());
        System.out.println(buffer.pop());
        buffer.push(5);
        System.out.println(buffer.pop());
    }

    static class Ringlinked{
        private Node head;
        private int pushPoint;
        private int popPoint;
        private int size;
        private int limit;

        public Ringlinked(int limit) {
            this.limit = limit;
            this.pushPoint = 0;
            this.popPoint = 0;
            this.size = 0;


            this.head =  new Node(null);
            Node h = head;
            for (int i = 0; i < (limit-1); i++) {
                Node node = new Node(null);
                h.next = node;
                node.last = h;
                h = node;
            }
        }

        public void push(T value){
            if(size == limit) {
                throw new RuntimeException("队列已满,无法push");
            }
            //找到对应Node
            Node node = node(pushPoint);
            // 直接替换value即可!
            node.value = value;
            pushPoint = nextIndex(pushPoint);
            size++;
        }

        public T pop(){
            if(size==0) {
                throw new RuntimeException("队列已空,无值pop");
            }
            Node node = node(popPoint);
            popPoint = nextIndex(popPoint);
            size --;
            T result = node.value;
            node.value = null;
            return result;
        }

        public boolean isEmpty(){
            return size==0;
        }
        public int size() {
            return size;
        }

        
        public Node node(int index) {
            Node x = head;
            for (int i = 0; i < index; i++) {
                x = x.next;
            }
            return x;
        }

        public int nextIndex(int index) {
            return index < (limit - 1)  ? index+1 : 0;
        }
    }
    
    static class Node {
        private T value;
        private Node next;
        private Node last;

        public Node(T value) {
            this.value = value;
        }
    }
}

数组实现环形队列:

public class RingArray {
    public static void main(String[] args) {
        MyQueue queue = new MyQueue(4);
        queue.push(0);
        queue.push(1);
        queue.push(2);
        queue.push(3);
        System.out.println(queue.pop());
        queue.push(4);

    }
}


class MyQueue{
    private Object[] arr;
    private int pushPoint;
    private int popPoint;
    private int size;
    private int limit;

    public MyQueue(int limit){
        this.arr = new Object[limit];
        pushPoint = 0;
        popPoint = 0;
        size = 0;
        this.limit = limit;
    }

    public void push(Object value) {
        if(size == limit) {
            throw new RuntimeException("队列已满,请稍后再加");
        }
        arr[pushPoint] = value;
        pushPoint = nextIndex(pushPoint);
        size ++ ;
    }

    public Object pop() {
        if(size == 0) {
            throw new RuntimeException("队列已空,请稍后再取");
        }
        Object result = arr[popPoint];
        popPoint = nextIndex(popPoint);
        size --;
        return result;
    }

    private boolean isEmpty(){
        return size==0;
    }

    private int nextIndex(int i){
        return i < limit-1 ? i+1:0;
    }

}

思路如下图:

3. 后言

无论是环形队列还是栈或者哈希表,实则数据结构的实现要么是数组要么是链表或者数组+链表。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5707350.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存