数据结构(7)--队列

来源:互联网 发布:linux tomcat自动关闭 编辑:程序博客网 时间:2024/06/06 02:10

对于Queue这个词大家熟悉么?我相信学习Android对于这个词熟悉的程度可谓是极深,毕竟Android内部很多的实现都是靠着队列.Handler、service内部实现也是.其实在我们生活当中,队列的作用就类似于说,我们去排队打饭(原谅我这个吃货),肯定是有人从前面打完饭走了,有人从后面排队进来…这样就是一个队列,那么大家都可以看出其中的特点了吧.
 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。

队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。

英文为:FIFO—>First In First Out,先进先出,后进后出

注意:队列也是有有着头结点(front)和队尾结点(rear)的.

队列的顺序存储:
在顺序存储里面,我们会经常发生”假溢出”现象.
front指向头元素,rear指向尾元素的下一个位置.因为顺序队列是限定个数,所以一旦前面的全部出去了,front后移,但是后面的插进来,会发现越界,但是实际上前面还有空位.这就是假溢出.
解决假溢出,就需要通过循环队列,循环队列的意思就是头尾相接,但是头尾相接又会出现一个循环有可能为空的问题,所以我们的解决方法是通过计数器的方法,来判定.

代码:

    public class ListQueue {     static final int defaultSize = 10; //默认队列的长度        int front;  //队头        int rear;   //队尾        int count;  //统计元素个数的计数器        int maxSize; //队的最大长度        Object[] queue;  //队列        public ListQueue() {            init(defaultSize);        }        public ListQueue(int size) {            init(size);        }        public void init(int size) {            maxSize = size;            front = rear = 0;            count = 0;            queue = new Object[size];        }        public void append(Object obj) throws Exception {            // TODO Auto-generated method stub            if (count > 0 && front == rear) {                throw new Exception("队列已满!");            }            //添加到尾节点            queue[rear] = obj;            rear = (rear + 1) % maxSize;            count++;        }           //从头结点删除,并且作为一个循环了实用front        public Object delete() throws Exception {            // TODO Auto-generated method stub            if (isEmpty()) {                throw new Exception("队列为空!");            }            Object obj = queue[front];            front = (front + 1) % maxSize;            count--;            return obj;        }        public Object getFront() throws Exception {            // TODO Auto-generated method stub            if (!isEmpty()) {                return queue[front];            } else {                return null;            }        }        public boolean isEmpty() {            // TODO Auto-generated method stub            return count == 0;        }    /**     * @param args     * @throws Exception      */    public static void main(String[] args) throws Exception {        // TODO Auto-generated method stub        ListQueue queue = new ListQueue();            queue.append("a");            queue.append("b");            queue.append("c");            queue.append("d");            queue.append("e");            queue.append("f");            queue.delete();            queue.delete();            while (!queue.isEmpty()) {                System.out.println(queue.delete());                }        }    } 链式队列:  链式队列其实就是特殊的单链表,只不过它只能尾进头出而已.说到链式队列,我们第一想到的就是结点的不同,我们要安排结点的构造.  结点类我就不写了:  测试类:(主要关注我们的front rear的变化就好了)     private QueueNode<T> front,rear;//声明两个结点     public LinkedQueue() {            this(null);        }        //初始化结点        public LinkedQueue(T element) {            if(element == null) {                front = new QueueNode<T>(null);                rear = front;            }else {                rear = new QueueNode<T>(element);                front = new QueueNode<T>(null,rear);            }        }        public int length(){            if(isEmpty()) return 0;            int k=1;            QueueNode<T> temp = front.getNext();            while(temp!=rear){                k++;                temp=temp.getNext();            }            return  k;        }        //获取第一个元素        public T getHead() {            if(isEmpty()) return null;            return front.getNext().getData();        }      //判断空         public boolean isEmpty() {          return front == rear;        }      //加入元素,从后面加入      public boolean add(T element) {            if(element == null) return false;            QueueNode<T> temp = front;            rear.setNext(new QueueNode<T>(element));            rear = rear.getNext();            return true;        }     //移除元素,前面走人,所以要对front进行修改      public T remove() {            if(isEmpty()) return null;            T element = front.getNext().getData();            if(length() == 1)                 rear = front;            else{                front.setNext(front.getNext().getNext());            }            return element;        }         //目标转换成字符串,拼接        public String toString() {            if(isEmpty()) return "[ ]";            StringBuffer sb = new StringBuffer("[ ");            QueueNode<T> temp = front.getNext();            while(temp != rear) {                sb.append(temp+" ");                temp = temp.getNext();            }            sb.append(temp+" ");            sb.append("]");            return sb.toString();        }    public static void main(String[] args) {        // TODO Auto-generated method stub             LinkedQueue<String> queue = new LinkedQueue<String>("A");            System.out.println("queue="+queue+"   queue.length="+queue.length());            queue.add("B");            System.out.println("queue="+queue+"   queue.length="+queue.length());            System.out.println("the removint element="+queue.remove());            System.out.println("queue="+queue+"   queue.length="+queue.length());    }

相信大家在查询的时候,会遇到一些类似与优先队列,其实优先队列的实现是差不多的,基本上就是我们逻辑上会多出一个优先级变量来设定优先级.

面试题:
设计含最小函数min()的栈,要求min、push、pop、的时间复杂度都是O(1)?

思路:
这里需要加一个辅助栈,用空间换取时间。辅助栈中,栈顶永远保存着当前栈中最小的数值。具体是这样的:原栈中,每次添加一个新元素时,就和辅助栈的栈顶元素相比较,如果新元素小,就把新元素的值放到辅助栈中,如果新元素大,就把辅助栈的栈顶元素再copy一遍放到辅助栈的栈顶;
重点方法:
minStack.peek()—>获取栈顶元素.

import java.util.Stack;/** * Created by smyhvae on 2015/9/9. */public class MinStack {    private Stack<Integer> stack = new Stack<Integer>();    private Stack<Integer> minStack = new Stack<Integer>(); //辅助栈:栈顶永远保存stack中当前的最小的元素    public void push(int data) {        stack.push(data);  //直接往栈中添加数据        //在辅助栈中需要做判断        if (minStack.size() == 0 || data < minStack.peek()) {            minStack.push(data);        } else {            minStack.add(minStack.peek());   //【核心代码】peek方法返回的是栈顶的元素        }    }    public int pop() throws Exception {        if (stack.size() == 0) {            throw new Exception("栈中为空");        }        int data = stack.pop();        minStack.pop();  //核心代码        return data;    }    public int min() throws Exception {        if (minStack.size() == 0) {            throw new Exception("栈中空了");        }        return minStack.peek();    }    public static void main(String[] args) throws Exception {        MinStack stack = new MinStack();        stack.push(4);        stack.push(3);        stack.push(5);        System.out.println(stack.min());    }}
0 0
原创粉丝点击