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

本文详细介绍了队列这一数据结构,包括其定义、特点、基本操作等,并通过Java语言实现了循环队列和链队列的具体操作,如入队、出队、判断队列是否为空等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

队列的定义

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

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

队列的抽象数据类型

C语言中的定义
InitQuene(*Q):初始化操作,建立一个空队列Q
DestroyQueue(*Q):若队列Q存在,则销毁它。
ClearQueue(*Q):将队列Q清空
QueueEmpty(Q):若队列Q为空,返回True,否则false
GetHead(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);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值