链式队列的八种基本运算[考研重点]

NOTICE: 代码测试没问题,直接复制就能跑!

环境:

Visual Stdio Code

 

链式队列和有头尾结点的单链表:

链式队列可以看成一个有头尾节点的单链表,但是它跟有头尾节点的单链表的唯一区别就是:链式队列只能从一端(rear 端)插入,从另一端(front 端)删除。

 

废话不多说,上代码:

#include
#include

#define MAXQSIZE 100  // 最大队列长度
#define ERROR 0
#define OK 1

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.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));  // 分配两个空间,一个 data 一个 next
    if(!Q.front)  return ERROR;    // 分配失败
    Q.front->next = NULL;

    return OK;
}//InitQueue

Status DestroyQueue(LinkQueue &Q)
{   // 销毁
    while(Q.front)      // 如果 front 不为空
    {
        Q.rear = Q.front->next;     // rear 指向 front 的直接后继结点
        free(Q.front);              // 释放 front 指向的结点
        Q.front = Q.rear;           // 将 front 后移
    }
    return OK;
}//DestroyQueue

Status EnQueue(LinkQueue &Q, QElemType e)
{   // 插入新元素 e
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p) return ERROR;                            // 分配失败
    p->data = e;                                    
    p->next = NULL;                                 
    Q.rear->next = p;                               // 插入的是队尾
    Q.rear = p;                                     // 队尾指针后移

    return OK;
}//EnQueue

Status DeQueue(LinkQueue &Q, QElemType &e)
{   // 删除队头元素, 用 e 返回
    if(Q.front == Q.rear) return ERROR;             // 判断队列是否为空
    QueuePtr p = Q.front->next;                     
    e = p->data;
    Q.front->next = p->next;
    if(Q.rear == p) Q.rear = Q.front;
    free(p);

    return e;
}//DeQueue

Status ClearQueue(LinkQueue &Q)
{   // 清空
    QueuePtr p, q;
    if(Q.front == Q.rear)  return ERROR;        // 队列为空
    Q.rear = Q.front;                          // 空队列的 rear 与 front 指向的是同一个结点
    p = Q.front->next;                          // p 指向 front 的直接后继结点
    Q.front->next = NULL;                       // 将 front 指向的结点的 next 置位空
    while(p)
    {
        q = p;                                  // 逐个删除
        p = p->next;
        free(q);
    }
    return OK;
}//ClearQueue

Status QueueEmpty(LinkQueue &Q)
{   // 判断队列是否为空
    return Q.front == Q.rear;
}//QueueEmpty

Status QueueLength(LinkQueue &Q)
{   // 输出非空队列的长度
    int i = 0;
    QueuePtr p;
    p = Q.front;
    while(p != Q.rear)
    {
        p = p->next;
        i++;
    }
    return i;
}//QueueLength

Status GetHead(LinkQueue &Q, QElemType e)
{   // 用 e 返回 Q 的队头元素
    if(Q.front == Q.rear)  return ERROR;
    e = Q.front->next->data;                // 队头元素可类比于单链表的首元结点
    return e;
}//GetHead

Status QueueTraverse(LinkQueue &Q)  // 书上还有一个形参: visit() 这个形参可以看成一个打印函数,这里我们用的是 printf()
{   // 打印队列元素
    QueuePtr p;
    if(Q.front == Q.rear)  return ERROR;    // 队列为空
    p = Q.front->next;                      // p 指向队列的队头结点
    while(p)
    {
        printf("%d\t", p->data);
        p = p->next;
    }
    return OK;
}//QueueTraverse

int main()
{
    int choice = 1;
    LinkQueue Q;
    QElemType e;
    printf("请输入序号进行相应的操作:\n");
    while(choice)
    {    
        printf("\n1.InitQueue   2.QueueLength   3.QueueTraverse   4.GetHead   5.ClearQueue \n6.EnQueue   7.DeQueue   8.QueueEmpty   9.DestroyQueue   0.exit\n");
        scanf("%d", &choice);
        switch (choice)
        {
            case 1:
                if(InitQueue(Q))
                    printf("\n初始化队列成功!\n");
                break;
            case 2:
                if(QueueEmpty(Q))
                    printf("\n队列为空\n");
                else
                    printf("\n队列的长度为:%d\n", QueueLength(Q));
                break;
            case 3:
                if(QueueEmpty(Q))
                    printf("\n队列为空\n");
                else
                {
                    printf("\n队列元素为:\n");
                    QueueTraverse(Q);
                }
                break;
            case 4:
                if(!QueueEmpty(Q))
                    printf("\n队列的队头元素为:%d\n", GetHead(Q, e));
                else
                    printf("\n队列为空\n");
                break;
            case 5:
                if(QueueEmpty(Q))
                    printf("\n队列为空!\n");
                else if(ClearQueue(Q))
                    printf("\n成功清空队列!\n");
                break;
            case 6:
                printf("\n请输入想要插入的的元素:\n");
                scanf("%d", &e);
                if(EnQueue(Q, e))
                    printf("\n插入成功!\n");
                else
                    printf("\n插入失败!\n");
                break;
            case 7:
                if(QueueEmpty(Q))
                    printf("\n队列为空!\n");
                else
                    printf("\n删除的队头元素为:%d\n", DeQueue(Q, e));
                break;
            case 8:
                if(QueueEmpty(Q))
                    printf("\n队列为空!\n");
                else
                    printf("\n队列不为空!\n");
                break;
            case 9:
                if(DestroyQueue(Q))
                    printf("\n销毁成功\n");
                else
                    printf("\n销毁失败!\n");
                break;
            case 0:
                choice = 0;
                break;
            default:
                printf("\n程序出错!\n");
                break;
        }
    }
    DestroyQueue(Q);
    return 0;
}

运行结果示意图就不贴出来了,太长了!

THE END!

你可能感兴趣的:(数据结构)