数据结构入门(五)-队列的定义与实现

来源:互联网 发布:c语言编程软件手机版 编辑:程序博客网 时间:2024/05/23 18:42

队列的定义

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端叫做队头。

队列的抽象数据类型

C语言中的定义InitQuene(*Q):初始化操作,建立一个空队列QDestroyQueue(*Q):若队列Q存在,则销毁它。ClearQueue(*Q):将队列Q清空QueueEmpty(Q):若队列Q为空,返回True,否则falseGetHead(Q,*e):若队列Q存在且非空,用e返回队列的队头元素EnQueue(*Q,e):若队列Q存在,插入新元素e到队列Q中并成为队尾元素DeQueue(*Q,*e):删除队列Q中对头元素,并用e返回其值。QueueLength(Q):返回队列Q的元素个数

但是顺序存储,若不是循环队列,算法的时间性能是不高的,但循环队列有面临着数组可能会溢出的问题,所以我们还要研究一下不需要担心队列长度的链式存储结构。

顺序队列

顺序队列存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表
顺序队列的表示

和顺序表一样,顺序队列利用内存中一段连续的存储空间来存放当前队列中的元素。由于队列的队头和队尾是变化的,设置两个指针front和real分别指示队头和队尾元素,它们的初值在队列初始化时应置为0

image
顺序队列的基本操作
入队时:将新元素插入rear所指的位置的后一位
出队时:删去front所指的元素,然后将front加1并返回被删元素
顺序表的溢出现象
- 下溢: 当队列为空时,做出队运算产生的溢出现象。下溢是正常现象,常用作程序控制转移的条件。
- 真上溢:当队列满时,做进栈运算产生空间溢出的现象。真上溢是一种出错状态,应设法避免。
- 假上溢:由于入队和出对操作中,头尾指针只增加不减小,致使被删元素的空间永远无法被重新利用。当队列中的实际元素的个数远远小于内存中分配的空间时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。

循环队列

如下图所示,这种头尾相连的顺序存储结构称为循环队列(circular queue)
循环队列中需要注意的几个重要问题
- 队空的判定条件,队空的判定条件是front=rear
- 堆满的判定条件是(rear+1)%QueueSize=front

image

    "使用Java 来模拟循环队列的实现原理"    package org.moxiu.StackandQueue;/** * Created by gyg on 2017/2/10. * 模拟循环队列的实现 */public class CircularQueue<E> {    //对象数组,队列最多存储a.length-1个对象    private Object[] element;    //默认初始化大小    private static final int DEFAULT_SIZE=10;    //队首下标    int front;    //队尾下标    int rear;    // 定义无参构造函数,默认长度为10        public CircularQueue(){            this(DEFAULT_SIZE);        }    //定义有参构造函数        public CircularQueue(int len){            element = new Object[len];            front = 0;            rear=0;        }    /**     *将一个对象追加到队列尾部     *@param obj     * return 队列满时返回false,否则返回true    */    public boolean push(E obj){        if((rear+1)%element.length==front){            return false;        }else{            element[rear]=obj;            rear=(rear+1)%element.length;            return true;        }    }    /**     *将一个队列的头部元素出队。     * @return     * @author gyg     */    public Object pop(){        if(rear == front){            return null;        }else{            Object obj = element[front];            element[front] = null;            front=(front+1)%element.length;            return obj;        }    }    /**     * 获取队列长度     * @param     */    public int size(){        if(rear>front)        {            return rear-front;        }        return front-rear;    }    /**     * 判断队列是否为空     * @param     */    public boolean isEmpty(){        return rear==front;    }    public static void main(String[] args){        CircularQueue queue = new CircularQueue(5);        queue.push("3");        queue.push("5");        System.out.println(queue.size()); //打印队列的长度        System.out.print(queue.isEmpty()); //判断队列是否为空        queue.pop(); //队列的头元素出队        int size = queue.size(); //使用变量定义队列的长度        for(int i=0;i<size;i++)        {            System.out.print(queue.pop()); //输出队列中所有的元素。        }    }

队列的链式存储结构及实现

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。
链队列的存储形式

image

    /** * Created by gyg on 2017/2/10. * 被类用于模拟链队列用java的实现 */public class LinkQueue<T> {    //链的数据结构    private class Node{        public T data;        public Node next;        //无参构造函数        public Node(){}        //有参构造函数        public Node(T data,Node next){            this.data=data;            this.next=next;        }    }    //队列头指针    private Node front;    //队列尾指针    private Node rear;    //队列长度    private int size=0;    public LinkQueue(){        Node n = new Node(null,null);        n.next=null;        front=rear=n;    }    /**     * 队列入队算法     */    public void push(T data){        //创建一个节点        Node s = new Node(data,null);        //将尾指针指向新加入的节点,将s节点插入队尾        rear.next=s;        rear=s;        size++;    }    /**     * 队列出队算法     */    public Object pop(){        if(rear==front){            try{                throw new Exception("堆栈为空");            }catch(Exception e){                e.printStackTrace();            }            return null;        }else{            //定义变量存储队头元素值            Node p = front.next;            T x = p.data;            //将队头元素所在的节点摘链            front.next=p.next;            //判断出队列长度是否为1            if(p.next==null)                rear=front;            //删除节点            p=null;            size--;            return x;        }    }    /**     * 求出队列长度     */        public int size(){            return size;        }    /**     * 判断队列是否为空     */        public boolean isEmpty(){            return size==0;        }    /**     * 重写toString方法     */    public String toString(){        if(isEmpty()){            return "[]";        }else{            StringBuilder sb = new StringBuilder("[");            for(Node current=front.next;current!=null;current=current.next){                sb.append(current.data.toString()+",");            }            int len = sb.length();            return sb.delete(len - 2,len).append("]").toString();        }    }    //测试    public static void main(String[] args){        LinkQueue<Integer> queue=new LinkQueue<Integer>();        queue.push(1);        queue.push(2);        queue.push(3);        queue.push(4);        queue.push(5);        queue.push(6);        System.out.println(queue);        System.out.println("出队:"+queue.pop());        System.out.println("队列长度="+queue.size());        System.out.println(queue);        System.out.println("出队:"+queue.pop());        System.out.println("队列长度="+queue.size());        System.out.println(queue);        System.out.println("出队:"+queue.pop());        System.out.println("队列长度="+queue.size());        System.out.println(queue);    }}
0 0
原创粉丝点击