链队列的基本算法

一、介绍

队列(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

 

posted @ 2019-10-17 14:57  XYQ全哥  阅读(2941)  评论(1编辑  收藏  举报