【数据结构】队列(顺序队列、循环队列、链队列)

文章目录

前言

队列也是一种线性表,其特殊性在于队列的基本操作是线性表的子集。队列按“先进先出”的规则进行操作,故称其为操作受限的线性表。


一、队列的定义

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

队列是一种先进先出(First In First Out)的线性表,简称FIFO。

允许插入的一端称为队尾(rear),允许删除的一端称为队头(front)

向队列中插入新的数据元素称为入队,新入队的元素就成为了队列的队尾元素。

从队列中删除队头元素称为出队,其后继元素成为新的队头元素。


二、队列的顺序存储结构

队列作为一种特殊的线性表,也同样存在两种存储结构:顺序存储结构和链式存储结构,可以分别用数组和链表来实现队列。

1.顺序队列的定义

用一组地址连续的存储单元,依次存放从队头到队尾的数据元素,称为顺序队列

需要附设两个指针:队头指针(front)队尾指针(rear),分别指向队头元素和队尾元素。

头尾指针和顺序队列中数据元素之间的关系示意图:

“假溢出”:如果在插入E的基础上再插入元素F,将会插入失败。因为rear==MAXSIZE,尾指针已经达到队列的最大长度。但实际上队列存储空间并未全部被占满,这种现象叫做“假溢出”。

假溢出的原因是顺序队列进行队头出队、队尾入队,造成数组前面会出现空闲单元未被充分利用。

2.循环队列定义

为了解决“假溢出”现象,使得队列的存储空间得到充分利用,一个巧妙的方法就是将顺序队列的数组看成一个头尾相接的循环结构。

队列的头尾相接的顺序存储结构称为循环队列

问题:当循环对列为空或满时,都是队尾指针等于队头指针,即rear==front 。当rear==front时,该是判满还是判空呢?

解决方案:

方案一:设置一个计数器,开始时计数器设为0,新元素入队时,计数器加1,元素出队,计数器减1。当计数器==MAXSIZE时,队满;计数器==0时,队空。

方案二:保留一个元素空间,当队尾指针指的空闲单元的后继单元是队头元素所在单元时,队满。

队满的条件为(Q.rear+1)%MAXSIZE==Q.front;

队空的条件为Q.rear==Q.front

3.循环队列的基本操作

typedef int ElemType
#define MAXSIZE 1024

/*循环队列的顺序存储结构*/
typedef struct
{
    ElemType data[MAXSIZE];
    int front;    //头指针
    int rear;    //尾指针
}SqQueue;

/*初始化一个空队列*/
int Init_SeQueue(SeQueue *Q)
{
    Q=(SeQueue *)malloc(sizeof(SeQueue));
    if(Q!=NULL)
    {
        Q->front=0;
        Q->rear=0;
    }
    return 1;
}

/*求队列长度*/
int QueueLength(SeQueue *Q)
{
    return (Q->rear-Q->front+MAXSIZE)%MAXSIZE;
}

/*判空*/
int SeQueue_Empty(SeQueue *Q)
{
    return Q->rear==Q->front;
}

/*判满*/
int SeQueue_Full(SeQueue *Q)
{
    return (Q->rear+1)%MAXSIZE==Q->front;
}

/*入队操作*/
int Enter_SeQueue(SeQueue *Q,ElemType e)
{
    if(SeQueue_Full(Q))
    {
        return 0;
    }

    Q->data[Q->rear]=e;
    Q->rear=(Q->rear+1)%MAXSIZE;
    return 1;
}

/*出队操作*/
int Delete_SeQueue(SeQueue *Q,ElemType e)
{
    if(SeQueue_Empty(Q))
    {
        return 0;
    }

    e=Q->data[Q->front];
    Q->front=(Q->front+1)%MAXSIZE;
    return 1;
}


三、队列的链式存储结构

1.链队列的定义

采用链式存储结构实现的队列称为链队列

为了使操作更加方便,将队头指针指向链队列的头结点,而队尾指针指向终端结点。 

空队列时,front和rear都指向头结点,即front==rear

链队列结构:

typedef int ElemType

/*结点结构*/
typedef struct QNode
{
    ElemType data;
    struct QNode *next;
}QNode,*QueuePtr;

/*链队列结构*/
typedef struct 
{
    QueuePtr front,rear;//队头、队尾指针
}LinkQueue;

2.链队列的基本操作

typedef int ElemType

/*结点结构*/
typedef struct QNode
{
    ElemType data;
    struct QNode *next;
}QNode,*QNodePtr;

/*链队列结构*/
typedef struct 
{
    QNodePtr front,rear;//队头、队尾指针
}LinkQueue,*LinkQueuePtr;

/*初始化一个空队列*/
int Init_LinkQueue(LinkQueuePtr Q)
{
    Q=(LinkQueuePtr)malloc(sizeof(LinkQueue));
    QNodePtr head=(QueuePtr)malloc(sizeof(QNode));
    
    if(head!=NULL && Q!=NULL)
    {
        head->next=NULL;
        Q->front=head;
        Q->rear=head;
    }
    return 1;
}

/*判空*/
int LinkQueue_Empty(LinkQueuePtr Q)
{
    return Q->front==Q->rear;
}

/*入队操作*/
int Enter_LinkQueue(LinkQueuePtr Q,ElemType e)
{
    QNodePtr s=(QNodePtr)malloc(sizeof(QNode));
    if(s==NULL){
        return 0
    }    
    //初始化新结点
    s->data=e;
    s->next=NULL;
    //建立新联系
    Q->rear->next=s;
    Q->rear=s;

    return 1;
}

/*出队操作*/
int Delte_LinkQueue(LinkQueuePtr Q,ElemType *e)
{
    QNodePtr p;
    if(LinkQueue_Empty(Q)){
        return 0
    } 
       
    //保留删除结点的信息
    p=Q->front->next;
    *e=p->data;

    //建立新联系
    Q->front->next=p->next;
   
    if(Q->rear==p)
    {
        Q->rear=Q->front)
    }
    
    free(p);

    return 1;
}

  • 34
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
顺序队列的实现: ```c #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 // 队列的最大长度 typedef struct{ int data[MAXSIZE]; int front; // 队头指针,指向队头元素 int rear; // 队尾指针,指向队尾元素的后一个位置 }SqQueue; // 初始化队列 void InitQueue(SqQueue *Q){ Q->front = 0; Q->rear = 0; } // 判断队列是否为空 int IsEmptyQueue(SqQueue Q){ if(Q.front == Q.rear) return 1; else return 0; } // 判断队列是否已满 int IsFullQueue(SqQueue Q){ if((Q.rear+1)%MAXSIZE == Q.front) return 1; else return 0; } // 入队 int EnQueue(SqQueue *Q, int data){ if(IsFullQueue(*Q)){ printf("Queue is full\n"); return 0; } Q->data[Q->rear] = data; Q->rear = (Q->rear+1)%MAXSIZE; return 1; } // 出队 int DeQueue(SqQueue *Q, int *data){ if(IsEmptyQueue(*Q)){ printf("Queue is empty\n"); return 0; } *data = Q->data[Q->front]; Q->front = (Q->front+1)%MAXSIZE; return 1; } // 输出队列 void PrintQueue(SqQueue Q){ if(IsEmptyQueue(Q)){ printf("Queue is empty\n"); return; } int i = Q.front; while(i != Q.rear){ printf("%d ", Q.data[i]); i = (i+1)%MAXSIZE; } printf("\n"); } int main(){ SqQueue Q; // 声明一个队列 InitQueue(&Q); // 初始化队列 int flag = 1, choice, data; while(flag){ // 循环操作 printf("1. EnQueue\n"); printf("2. DeQueue\n"); printf("3. PrintQueue\n"); printf("0. Exit\n"); printf("Enter your choice: "); scanf("%d", &choice); switch(choice){ case 0: flag = 0; break; case 1: printf("Enter data to Enqueue: "); scanf("%d", &data); if(EnQueue(&Q, data)) printf("Enqueue %d successfully!\n", data); break; case 2: if(DeQueue(&Q, &data)) printf("Dequeue %d successfully!\n", data); break; case 3: PrintQueue(Q); break; default: printf("Invalid choice\n"); } } return 0; } ``` 链队列的实现: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node{ // 链队列结点的定义 int data; struct Node *next; }Node, *pNode; typedef struct{ // 链队列的定义 pNode front; // 队头指针 pNode rear; // 队尾指针 }LinkQueue; // 初始化队列 void InitQueue(LinkQueue *Q){ Q->front = Q->rear = (pNode)malloc(sizeof(Node)); Q->front->next = NULL; } // 判断队列是否为空 int IsEmptyQueue(LinkQueue Q){ if(Q.front == Q.rear) return 1; else return 0; } // 入队 void EnQueue(LinkQueue *Q, int data){ pNode p; p = (pNode)malloc(sizeof(Node)); p->data = data; p->next = NULL; Q->rear->next = p; Q->rear = p; } // 出队 int DeQueue(LinkQueue *Q, int *data){ if(IsEmptyQueue(*Q)){ printf("Queue is empty\n"); return 0; } pNode p = Q->front->next; *data = p->data; Q->front->next = p->next; if(Q->rear == p) // 如果队列中只有一个元素 Q->rear = Q->front; free(p); return 1; } // 输出队列 void PrintQueue(LinkQueue Q){ if(IsEmptyQueue(Q)){ printf("Queue is empty\n"); return; } pNode p = Q.front->next; while(p){ printf("%d ", p->data); p = p->next; } printf("\n"); } int main(){ LinkQueue Q; // 声明一个队列 InitQueue(&Q); // 初始化队列 int flag = 1, choice, data; while(flag){ // 循环操作 printf("1. EnQueue\n"); printf("2. DeQueue\n"); printf("3. PrintQueue\n"); printf("0. Exit\n"); printf("Enter your choice: "); scanf("%d", &choice); switch(choice){ case 0: flag = 0; break; case 1: printf("Enter data to Enqueue: "); scanf("%d", &data); EnQueue(&Q, data); printf("Enqueue %d successfully!\n", data); break; case 2: if(DeQueue(&Q, &data)) printf("Dequeue %d successfully!\n", data); break; case 3: PrintQueue(Q); break; default: printf("Invalid choice\n"); } } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值