(一)基本概念
队列是一种特殊的线性表(先进先出),特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。 先进先出的数据结构
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。 队列就像一个两端相通的水管,只允许一端插入,另一端取出,先放入管中的球先从管中拿出,如图所示。
(二)顺序队列
队列结点类型:
typedef char Data;
typedef struct
{
Data data[MaxSize];
int front ,rear;
}SqQueue;//声明顺序队列类型
顺序队列: 因为存在假溢出现象,故不怎么用;而通常采用一种解决队列“假溢出”问题的方法:环形队列去代替。
顺序队列中,如果没有按照取余数的方式入队,就会在数组的最后,出现数组溢出(rear==MaxSize-1),此时,即使数组前面有空间,也不能正确入队,形成假溢出。
//假溢出时:sq.rear == maxsize-1,但队列中实际容量并未达到最大容量的现象;
环形队列:
初始化:
//初始化队列
SqQueue* InitQueue()
{
SqQueue *q = (SqQueue*)malloc(sizeof(SqQueue));
assert(q);
q->front = q->rear = 0;
return q;
}
入队:
//进队
void enQueue(SqQueue* q,Data e)
{
if ((q->rear + 1) % MaxSize == q->front)
{
printf("队列已满,插入不了!");
return;
}
q->data[q->rear] = e;
q->rear = (q->rear + 1) % MaxSize;//q->rear = q->rear + 1;普通顺序队列
}
//出队
void deQueue(SqQueue* q )
{
if (q->front == q->rear)
{
printf("队列为空,出不了!");
return;
}
q->front = (q->front + 1)%MaxSize;//普通顺序队列:q->front = q->front + 1 ;
}
遍历:遍历操作还有很多变形,比如说进行计算队列中含有多少元素。
void Print(SqQueue* q)
{
if (q->front == q->rear)
{
return;
}
for (int i = q->front; i < q->rear; i++)
{
printf("%c", q->data[i]);
}
}
全部代码:
(二)链队列
链队列就是将队列的元素用链表的形式来表示,设置头节点和尾结点来控制队列的尾入头出。
链队结点类型:
#define MaxSize 100
typedef char Data;
typedef struct DataNode
{
Data data;
struct DataNode *next;
} DataNode;//声明链队数据结点类型
typedef struct
{
DataNode* front;
DataNode* rear;
}LinkQueue;//声明链队类型
初始化链队:
LinkQueue* InitQueue()
{
LinkQueue*q = (LinkQueue*)malloc(sizeof(LinkQueue));
assert(q);
q->front = q->rear = NULL;
return q;
}
销毁队列:
void DestoryQueue(LinkQueue* q)
{
DataNode* p = q->front, * r;
if (p != NULL)
{
r = p->next;
while (r != NULL)
{
free(p);
p = r; r = p->next;
}
}
free(p);
}
进队:
void enQueue(LinkQueue* q,Data e)
{
DataNode* p = (DataNode*)malloc(sizeof(DataNode));
assert(p);
p->data = e;
p->next = NULL;
if (q->rear == NULL)
{
q->front = q->rear = p;//链队为空,新结点即是队首又队尾结点。
}
else
{
q->rear->next = p;//将p结点链到队尾,并将rear指向它
q->rear = p;
}
}
出队:
void deQueue(LinkQueue* q )
{
DataNode* p;
if (q->rear == NULL) return;
p = q->front;//p指向队列第一个数据结点
if (q->front == q->rear)
{
q->front = q->rear = NULL;
}
else
q->front = q->front->next;
free(p);
}
遍历:
void Print(LinkQueue*q)
{
DataNode* p = q->front;
if (p != NULL)
{
while (p->next != NULL)
{
printf("%c", p->data);
p = p->next;
}
}
assert(p);
printf("%c", p->data);
}
全部代码:
#include
#include
#include
#include
#define MaxSize 100
typedef char Data;
typedef struct DataNode
{
Data data;//数据域
struct DataNode *next;//指针域
} DataNode;//声明链队数据结点类型
typedef struct
{
DataNode* front;//队首指针
DataNode* rear;//队尾指针
}LinkQueue;//声明链队类型
//初始化队列
LinkQueue* InitQueue()
{
LinkQueue*q = (LinkQueue*)malloc(sizeof(LinkQueue));
assert(q);
q->front = q->rear = NULL;
return q;
}
//销毁队列
void DestoryQueue(LinkQueue* q)
{
DataNode* p = q->front, * r;
if (p != NULL)
{
r = p->next;
while (r != NULL)
{
free(p);
p = r; r = p->next;
}
}
free(p);
}
//判断队列是否为空
bool QueueEmpty(LinkQueue* q)
{ return q->rear == NULL;
}
//进队
void enQueue(LinkQueue* q,Data e)
{
DataNode* news = (DataNode*)malloc(sizeof(DataNode));//创建新结点
assert(news);
news->data = e;
news->next = NULL;
if (q->rear == NULL)
{
q->front = q->rear = news;//链队为空,新结点即是队首又队尾结点。
}
else
{
q->rear->next =news;//将p结点链到队尾,并将rear指向它
q->rear = news;
}
}
//出队
void deQueue(LinkQueue* q )
{
DataNode* p;
if (q->rear == NULL) return;
p = q->front;//p指向队列第一个数据结点
if (q->front == q->rear)
{
q->front = q->rear = NULL;
}
else
q->front = q->front->next;
free(p);
}
void Print(LinkQueue*q)
{
DataNode* p = q->front;
if (p != NULL)
{
while (p->next != NULL)
{
printf("%c", p->data);
p = p->next;
}
}
assert(p);
printf("%c", p->data);//补缺
}
int main()
{
Data e = ' ';
LinkQueue* q = InitQueue();
printf("依次进队列元素a,b,c,d\n");
printf("链队为%s\n", QueueEmpty(q) ? "空" : "非空");
enQueue(q, 'a');
enQueue(q, 'b');
enQueue(q, 'c');
enQueue(q, 'd');
Print(q);printf("链队为%s\n", QueueEmpty(q) ? "空" : "非空"); printf("\n依次删除队列元素:\n");
deQueue(q);
deQueue(q);
Print(q); printf("\n");
printf("链队为%s\n", QueueEmpty(q) ? "空" : "非空");
enQueue(q,'d');
Print(q);
return 0;
}