数据结构5 —————队的概念和运算
文章目录
一. 队的概念
1.定义
- 栈是一种只允许在一端进行插入,在另一端进行删除的线性表,和栈类似都是一种操作受限的线性表
2. 相关概念
- 队头:允许进行删除的一端称为队顶
- 队尾:允许进行插入的一端称为队底
- 出队:在队头进行删除操作
- 入队:在队尾进行插入操作
- 空队:队内没有元素
3. 特点
先进先出。
4.栈的ADT定义
Data
同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。
Operation
InitQueue(*Q):初始化操作,建立一个空队列Q。
DestroyQueue(*Q):若队列Q存在,則销毀它。
ClearQueue(*Q):将队列 Q 清空。
QueueEmpty(Q):若队列Q为空,送回true,否則退回false。
GetHead(Q, *e):若队列Q存在且非空,用e返因队列Q的队头元素。
EnQueue(*Q,e):若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
DeQueue(*Q, *e):刪除队列Q中队头元素,并用e返回其值。
QueueLength(Q):送回队列Q的元素个教。
endADT
5. 栈的存储结构
- 顺序存储结构(循环队列)
- 链式存储结构(链栈)
6.图示
二. 链队列
1.结构定义
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int Elemtype;
//节点
typedef struct node{
Elemtype date;
struct node *next;
}QNode;
//链队的头尾指针
typedef struct{
QNode *front;
QNode *rear;
}LQueue;
2.说明
- 用链表作为队的存储形式(非线性存储),靠近头结点一端为队头,另一端为队尾,使用两个指针,一个指向队头,一个指向队尾
- 空栈情况:指向队头的坐标等于指向队尾的坐标。
- 入队:创建新的节点,并将它链接到队尾,尾指针移动
- 出队:先判空,如果不是空栈将头结点的下一个节点删除
3.图示
4.初始化
//初始化
LQueue *InitLQueue(){
LQueue *qL;
QNode *p;
qL=(LQueue *)malloc(sizeof(LQueue));
p=(QNode *)malloc(sizeof(QNode));
p->next=NULL;
qL->front=qL->rear=p;
return qL;
}
5.入队
//入队
int InLQueue(LQueue *qL ,Elemtype x){
QNode *p;
p=(QNode *)malloc(sizeof(QNode));
p->date=x;
p->next=NULL;
qL->rear->next=p;
qL->rear=p;
return TRUE;
}
6.判断是否为空
//判空队
int EmptyLQueue(LQueue *qL){
if(qL->front==qL->rear)
return TRUE;
return FALSE;
}
7.出队
//出队
int QutLQueue(LQueue *qL ,Elemtype *x){
QNode *p;
if(!EmptyLQueue(qL)){ //栈不空
p=qL->front->next;
*x=p->date;
qL->front->next=p->next;//删除
free(p);
if(qL->front->next ==NULL)
qL->rear = qL->front;
return TRUE;
}
printf("空队\n");
return FALSE;
}
8.链栈的其他方法
可将链表设置为循环链表,只设置尾指针,也可以完成链表的所有操作,具体实现可见我最后代码链接里的代码
三. 循环队列
1.结构定义
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define MAXSIZE 10
typedef int Elemtype;
typedef struct{
Elemtype date[MAXSIZE];
int front,rear;
}CSeQeue;
2.说明
- 循环队列是使用数组作为存储形式(线性存储),开始时靠近下标0为队头,另一端为队尾,之后队尾到达数组的末尾后,如果队头不在0处,那么队尾从靠近0的一端重新开始,形成一个环
- 这个示例代码中,使用的牺牲一个空间来判断队空,还是队满
- 队空:队尾==队头
- 队满:队尾+1 == 队头
- 入栈:
qS->rear=(qS->rear+1)%MAXSIZE;//计算入对后队尾的位置
qS->date[qS->rear]=x;//入队
- 出栈:
qS->front=(qS->front+1)%MAXSIZE;//计算出队后的队头位置
*x = qS->date[qS->front];//出队
3.图示
4.初始化
//初始化
CSeQeue *InitSeQueue(){
CSeQeue *qS;
qS=(CSeQeue *)malloc(sizeof(CSeQeue));
qS->rear=qS->front=MAXSIZE-1;
return qS;
}
5.入队
//入队
int InSeQueue(CSeQeue *qS ,Elemtype x){
if((qS->rear+1)%MAXSIZE==qS->front){
printf("队满\n");
return FALSE;
}
qS->rear=(qS->rear+1)%MAXSIZE;
qS->date[qS->rear]=x;
return TRUE;
}
6.判断是否为空
//判空
int EmptySeQueue(CSeQeue *qS){
if(qS->front == qS->rear)
return TRUE;
return FALSE;
}
7.出队
//出队
int QutSeQueue(CSeQeue *qS ,Elemtype *x){
if(!EmptySeQueue(qS)){
qS->front=(qS->front+1)%MAXSIZE;
*x = qS->date[qS->front];
return TRUE;
}
printf("队空\n");
return FALSE;
}
8.循环队列的其他实现方法
设置一个标志来判断是队空还是队满
不使用队尾指针,改为长度