数据结构与算法之队列【四】

306 阅读3分钟

栈是后进先出的数据结构,队列是先进先出的数据结构

栈的插入和删除数据项的命名方法很标准,称为push和pop。 队列的方法,没有明确的标准,插入可以为put和add,enque等,删除可以称为delete,get,remove,deque。

理解队列:队列的作用就像买票一样,人们排成一队,第一个进队列的人先买到票,最后排队的人最后才能买到票。

队列实现:使用数组作为底层容器实现一个队列操作封装,与排队买票不同的是,当前面的人离开后其他人都向前移动,而队列并没有向前移动,只需要将指针标记队头和队尾,队列发生变化时,移动指针就可以,而数据项的位置不变,但是随着队头元素的不断移除,数组前面空出的位置也会越来越多,当队尾指针移动到最后的位置时,即使队列没有满,也不能再插入新的数据项了。

普通队列

解决的办法是环绕式处理,让队尾指针回到数组的第一个下标,这就是循环队列,虽然存储上是线性的,但是它在逻辑上时一个首尾相接的环形。

    public class Queue{
        private int[] arr[];//队列容器
        private int maxSize;//初始化数组的长度
        private int tail;//队尾
        private int head;//队头
        private int length;//数组实际应用的长度
        
        //构造方法,初始化队列
        public Queue(int maxSize){
            this.maxSize = maxSize;
            head=0;
            tail=-1;
            length=0;
        }
        //插入数据
        public void insert(int element) throws Exception{
            if(length==maxSize){
                throws new Exception("队列已满");
            }
            //如果队尾指针到了队尾,那么就插入到数组的第一个位置
            if(tail=maxSize-1){
                tail=-1;
            }
            arr[++tail] = element;
            length++;
        }
        //删除数据
        public int remove() throws Exception{
            if(length ==0){
                throws new Exception("队列为空");    
            }
            int element = arr[head++];
            //如果队头指针到数组末端,则移除数组第一个元素
            if(head==maxSize){
                head=0;
            }
            length--;
            return element;
        }
        //查看队头元素
        public int peek(){
            if(length==0){
                throws new Exception("队列为空");
            }
            return arr[head];
        }
        //获得队列长度
        public int size(){
            return length;
        }
        //判断队列是否为空 
        public boolean isEmpty(){
            return (length==0);
        }
        //判断队列是否满
        public boolean isFull(){
            return (length==maxSize);
        }
    }

优先级队列

和普通队列相同,优先级队列有一个队头和队尾,并且也是从队头移除数据,从队尾插入数据,不同的是在优先级队列中,数据项按数据的值进行排序,数据在插入之前会按顺序插入到合适的位置。

除了可以快速访问优先级最高的数据,优先级队列还可以实现很快的插入,因此,优先级队列通常使用堆来实现,因为还没有学到堆,暂时使用数组来实现。

优先级队列和普通队列的实现方式有着更大的区别。

优先级队列的插入需要移动元素来找到应该插入的位置,所以循环队列那种不需要移动元素的优势就不太明显了,所以在实现上,使数组的第一个位置永远是队尾,数组的最后一个元素永远是队头。

    public class PriorityQueue{
        private int[] arr;
        private int maxSize;//数组的初始化长度
        private int length;//数组的实际应用长度

        //构造方法,初始化数组
        public PriorityQueue(int maxSize){
            arr=new int[maxSize];
            length=0;
        }
        //插入数据
        public void insert(int element){
            if(isFull()){
                System.out.pringln("队列已满");
                return;
            }
            //如果队列为空,则将数据插入到第一个位置
            if(length==0){
                arr[length++] = element;
            }else{
                for(int i=length-1;i>=0;i--){
                    if(element>arr[i]){
                        arr[i+1] = arr[i];
                    }else{
                        break;
                    }
                }
                arr[i+1] = element;
            }
        }
        public int remove(){
            if(isEmpty()){
                System.out.println("队列为空");
                return;
            }
            return arr[--length];
        }
        public int min(){
            if(isEmpty()){
                System.out.println("队列为空");
                return;
            }
            return arr[length-1]
        }
        //判断队列满
        public boolean isFull(){
            return (length==maxSize);
        }
        public boolean isEmpty(){
            return (length==0)
        }
    }