zoukankan      html  css  js  c++  java
  • 链队列的基本算法

    一、介绍

    队列(Queue),计算机中一种常用的数据结构,具有先进先出FIFO的特点。

    通俗一点,就跟生活中超市购物结账排队一样,靠前的结账先走,新来的排在后面等待。

    对于队列中的元素,一般都在队头出队,在队尾入队,队头用Q.front表示,队尾用Q.rear表示。

    队列的实现有两种方式,通过数组或者链表实现。基于数组实现的队列一般称作顺序队列,基于链表实现的队列一般称作链式队列。

    链式队列中,有两个指针,分别是队头指针和队尾指针。为了操作方便,可以给链队列添加一个头结点,并令头指针指向头结点。

    空队列判决条件:头指针和尾指针均指向头结点。也即Q.front == Q.rear。 

    本文采用链表实现队列,链队列的操作即为单链表的插入和删除的特殊情况,只是尚需修改尾指针或头指针。

    二、示图

     

    三、算法

    #define QUEUE_OVERFLOW  -1
    #define OK               1
    #define ERROR            0
    #define TRUE             1
    #define FALSE            0
    
    typedef int QElemType;
    typedef int Status;
    
    /// ----- 单链队列 ------- 队列的链式存储结构
    typedef struct QNode {
        QElemType  data;
        struct QNode *next;
    }QNode, *QueuePtr;
    
    typedef struct  {
        QueuePtr front; //队头指针
        QueuePtr rear;  //队尾指针
    }LinkQueue;
    
    /// --- 基本操作的函数原型说明 -----
    Status InitQueue(LinkQueue &Q);             //构造一个空的队列Q
    Status DestroyQueue(LinkQueue &Q);          //销毁队列Q,Q不再存在
    Status ClearQueue(LinkQueue &Q);            //将队列Q清空
    Status QueueEmpty(LinkQueue  Q);            //判断队列Q是否为空,若空,返回TURE, 否则,返回FALSE
    int    QueueLength(LinkQueue Q);            //返回Q的元素个数,也即队列的长度
    Status GetHead(LinkQueue Q, QElemType &e);  //若队列Q不为空,则用e返回Q的队头元素,并返回OK;否则,返回ERROR
    Status EnQueue(LinkQueue &Q, QElemType e);  //插入元素e为Q的新的队尾元素
    Status DeQueue(LinkQueue &Q, QElemType &e); //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则,返回ERROR
    void   QueueVisit(LinkQueue &Q);            //访问队列元素

    四、代码

    Status InitQueue(LinkQueue &Q) {
    
        //构造一个空队列Q
        Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
        if (!Q.front) exit(QUEUE_OVERFLOW); //存储分配失败
        Q.front->next = NULL;
    
        return OK;
    }
    
    Status DestroyQueue(LinkQueue &Q){
    
        //销毁队列Q
        while (Q.front){
            Q.rear = Q.front->next;
            free(Q.front); //从队头取出每一个元素并释放内存,Q.rear作为一个临时指针使用
            Q.front = Q.rear;
        }
        cout<<"队列已销毁"<<endl;
        return OK;
    }
    
    Status ClearQueue(LinkQueue &Q){
    
        //清空队列Q
        Q.rear = Q.front;
        cout<<"队列已清空"<<endl;
        return OK;
    }
    
    Status QueueEmpty(LinkQueue Q){
    
        //判断队列Q是否为空
        if (Q.front == Q.rear) {
            cout<<"队列为空"<<endl;
            return TRUE;
        }
        cout<<"队列不为空"<<endl;
        return FALSE;
    }
    
    int QueueLength(LinkQueue Q){
    
        //获取队列的长度
        QNode *p = Q.front->next;
        int len = 0;
        while (p){
            len++;
            p = p->next;
        }
        cout<<"队列长度:"<<len<<endl;
        return len;
    }
    
    Status GetHead(LinkQueue Q, QElemType &e){
    
        //获取队头元素
        if (Q.front == Q.rear) {
            return FALSE;
        }
        QNode *p = Q.front->next;
        e = p->data;
        cout<<"队头元素:"<<e<<endl;
        return OK;
    }
    
    Status EnQueue(LinkQueue &Q, QElemType e){
    
        //插入元素e为Q的新的队尾元素
        QNode *p = (QueuePtr)malloc(sizeof(QNode));
        if (!p) exit(QUEUE_OVERFLOW);
        p->data = e;
        p->next = NULL;
        Q.rear->next = p;//当前队尾指针的next指针指向新元素
        Q.rear = p;//修改队尾指针
        cout<<"入队:"<<e<<endl;
        return OK;
    }
    
    Status DeQueue(LinkQueue &Q, QElemType &e){
    
        //删除队头元素
        if (Q.front == Q.rear) return ERROR;
        QNode *p = Q.front->next;
        e = p->data;
        Q.front->next = p->next;
        cout<<"出队:"<<e<<endl;
        if (Q.rear == p) {
            Q.rear = Q.front;
        }
        free(p);
        return OK;
    }
    
    void QueueVisit(LinkQueue &Q){
    
        if (Q.front == Q.rear){
            cout<<"队列为空"<<endl;
            return;
        }
    
        //访问队列元素
        QNode *p = Q.front->next;
        printf("队列顺序为:");
        while (p){
            QElemType e = p->data;
            p = p->next;
            printf("%d ",e);
        }
        cout<<endl;
    }

    五、测试 

    int main() {
    
        //构造队列
        LinkQueue queue;
        if (InitQueue(queue) == OK){
            for (int i = 1; i <= 10; ++i) {
                EnQueue(queue,i);//入队列
            }
        }
    
        //判断队列是否为空
        QueueEmpty(queue);
    
        //访问队列元素
        QueueVisit(queue);
    
        //获取队列长度
        QueueLength(queue);
    
        //获取队头元素
        QElemType e;
        GetHead(queue, e);
    
        //出队列
        for (int i=1; i<5 ; i++) {
            DeQueue(queue, e);
        }
        QueueVisit(queue);
    
        //清空队列
        ClearQueue(queue);
        QueueEmpty(queue);
    
        //销毁队列
        DestroyQueue(queue);
    
        return 0;
    }

    六、打印

    /Users/xiayuanquan/CLionProjects/queueTest/cmake-build-debug/queueTest
    入队:1
    入队:2
    入队:3
    入队:4
    入队:5
    入队:6
    入队:7
    入队:8
    入队:9
    入队:10
    队列不为空
    队列顺序为:1 2 3 4 5 6 7 8 9 10 
    队列长度:10
    队头元素:1
    出队:1
    出队:2
    出队:3
    出队:4
    队列顺序为:5 6 7 8 9 10 
    队列已清空
    队列为空
    队列已销毁
    
    进程已结束,退出代码 0
  • 相关阅读:
    LTE-TDD随机接入过程(3)-RAR(MSG2)以及MSG1的重传
    《javascript设计模式》读书笔记一(接口)
    数据结构——算法之(033)(两个有序单链表合并为一个有序的单链表)
    利用redis和php-resque实现后台任务
    最能毁掉程序猿健康的几件事
    springMVC4(11)使用注解完毕数据格式化
    Linux
    Linux
    Linux
    Fluent_Python_Part4面向对象,11-iface-abc,协议(接口),抽象基类
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/11692065.html
Copyright © 2011-2022 走看看