DATE:2020.4.21
1、队列的定义
队列是一种特殊的线性表,特殊在于队列限定在一端进行插入,在另一端进行删除。
队列有两种物理存储结构:
1、顺序队列:循环队列是为了解决队列的“假溢出”现象。
2、链队列:队列的链式存储
2、队列的基本操作(创建、入队、出队、遍历)
#include <stdio.h>
#include <stdlib.h>
#define MAX_DATA_SIZE (20)
typedef int QElemType;
// 1、循环队列的顺序存储结构
typedef struct SqQueue
{
QElemType data[MAX_DATA_SIZE];
int front; // 头指针
int rear; // 尾指针,若队列不空,则指向队列尾元素的下一个位置
} SqQueue;
// 1.1、初始化一个空队列Q
int InitQueue(SqQueue *Q)
{
Q->front = 0;
Q->rear = 0;
return 0;
}
// 1.2、返回队列Q中的元素个数
int GetLengthQueue(SqQueue *Q)
{
return ((Q->rear - Q->front + MAX_DATA_SIZE) % MAX_DATA_SIZE);
}
// 1.3、入队列:若队列未满,则插入元素e为Q新的队尾元素
int EnterQueue(SqQueue *Q, QElemType e)
{
if ((Q->rear + 1) % MAX_DATA_SIZE == Q->front)
{
printf("队列满了,无法插入新元素!\n");
return -1;
}
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAX_DATA_SIZE;
return 0;
}
// 1.4、出队列:若队列不空,则删除队头元素,并用e返回其值
int DeQueue(SqQueue *Q, int *e)
{
if (Q->rear == Q->front)
{
printf("空栈!\n");
return -1;
}
*e = Q->data[Q->front];
Q->front = (Q->front+1) % MAX_DATA_SIZE;
return 0;
}
// 2、队列链式存储结构
typedef struct Node
{
QElemType data;
struct Node *next;
} Node, *LinkListPtr;
typedef struct LinkQueue
{
LinkListPtr front, rear;
} LinkQueue;
// 2.1 队列初始化为空队列
int InitLinkQueue(LinkQueue *LQ)
{
LinkListPtr QueueHead;
QueueHead = (LinkListPtr) malloc(sizeof(Node));
if (NULL == QueueHead)
{
printf("QueueHead malloc error!\n");
return -1;
}
QueueHead->next = NULL;
LQ->front = QueueHead;
LQ->rear = QueueHead;
return 0;
}
// 2.2 返回队列长度:遍历整个链表
int GetLengthLinkQueue(LinkQueue *LQ)
{
LinkListPtr front = NULL;
int length = 0;
front = LQ->front;
while (front != LQ->rear)
{
front++;
length++;
}
return length;
}
// 2.3 入队操作:在链表尾部插入结点,对于链队列不存在满的情况
int EnterLinkQueue(LinkQueue *LQ, int ele)
{
LinkListPtr newNode = (LinkListPtr) malloc(sizeof(Node));
if (NULL == newNode)
{
printf("newNode malloc error!\n");
return -1;
}
newNode->data = ele;
newNode->next = NULL;
LQ->rear->next = newNode;
LQ->rear = newNode; // 类似链表的尾插法
return 0;
}
// 2.4 出队操作:若队列非空,则将链表中第一个结点删除,并返回其值给ele
int DeleteLinkQueue(LinkQueue *LQ, int *ele)
{
LinkListPtr Linkfront;
if (LQ->front == LQ->rear)
{
printf("空队列!\n");
return -1;
}
Linkfront = LQ->front->next;
*ele = Linkfront->data;
LQ->front->next = Linkfront->next;
if (LQ->rear == Linkfront)
{
LQ->rear = LQ->front;
}
free(Linkfront);
Linkfront = NULL;
return 0;
}
// 2.5 遍历输出队列元素:从队头到队尾
int TraverseLinkQueue(LinkQueue *LQ)
{
LinkListPtr traversePtr = NULL;
if (LQ->front == LQ->rear)
{
printf("空队列!\n");
return -1;
}
traversePtr = LQ->front->next; //指向头结点的下一个结点
while (traversePtr)
{
printf("%d\t ", traversePtr->data);
traversePtr = traversePtr->next;
}
printf("\n");
return 0;
}
// test demo
int main(int argc, char * argv[])
{
int ele = 0;
LinkQueue LQ;
// 1. 队列初始化
InitLinkQueue(&LQ);
// 2.入队列
EnterLinkQueue(&LQ, 1);
TraverseLinkQueue(&LQ);
EnterLinkQueue(&LQ, 2);
TraverseLinkQueue(&LQ);
EnterLinkQueue(&LQ, 3);
TraverseLinkQueue(&LQ);
// 3.出队列
DeleteLinkQueue(&LQ, &ele);
printf("出队元素: %d \n", ele);
TraverseLinkQueue(&LQ);
DeleteLinkQueue(&LQ, &ele);
printf("出队元素: %d \n", ele);
TraverseLinkQueue(&LQ);
DeleteLinkQueue(&LQ, &ele);
printf("出队元素: %d \n", ele);
TraverseLinkQueue(&LQ);
return 0;
}
本文深入探讨了队列数据结构的两种主要实现方式:顺序队列和链队列。通过详细的代码示例,讲解了队列的基本操作,包括创建、入队、出队和遍历。特别关注了循环队列解决假溢出问题的方法,以及链队列的灵活应用。
1856

被折叠的 条评论
为什么被折叠?



