005 数据结构_队列——“C”
前言
小留言:哈喽!各位CSDN的uu们,我是你的好友Fan_558,本文是Fan——数据结构与算法学习之路专栏的第五篇文章,本文采用单链表的形式实现队列,希望我的文章可以给您带来一定的帮助
引入
队列的概念:
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
举一个简单例子,我们在饭堂买饭,此时你是第5号,前面还有1,2,3,4号,当第一个人拿到他的饭后,此时1号从队列中移除,这时又来了一个人,这个只能从队尾开始排。即先进先出
测试用例
已通过如下测试用例,请放心学习
void Test1()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
printf("队尾元素为:%d\n", QueueBack(&q));
QueuePush(&q, 2);
printf("个数:%d\n", QueueSize(&q));
printf("队尾元素为:%d\n", QueueBack(&q));
QueuePush(&q, 3);
printf("队头元素为:%d\n", QueueFront(&q));
QueuePush(&q, 4);
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
}
void Test2()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
printf("队头元素为:%d\n", QueueFront(&q));
printf("队尾元素为:%d\n", QueueBack(&q));
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
printf("个数:%d\n", QueueSize(&q));
QueueDestroy(&q);
}
int main()
{
Test1();
Test2();
return 0;
}
实现步骤
1、队列——初始化
解析:这里用两个结构体的原因: 使用结构体可以将相关的变量放在一起,从而使得代码更具可读性 这里把_front与_rear放在一起作为队列的队头与队尾,这一组相关数据用一个Queue类型的结合体联合起来,_next与_data是一个节点的组成成分因此用一个QNode类型的结构体把它们联合起来。 而_front与_rear又是QNode结构体的结构体指针,因此可以用这两个结构体指针来访问QNode结构体的成员变量_next与_data。// 链式结构:表示队列
typedef int QDataType;
//节点
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* _front;
QNode* _rear;
}Queue;
// 初始化队列
void QueueInit(Queue* q)
{
assert(q);
q->_front = NULL;
q->_rear = NULL;
}
2、队列——销毁
void QueueDestroy(Queue* q)
{
assert(q);
QNode* cur = q->_front; //保存当前节点
while (cur)
{
QNode* next = cur->_next; //保存当前节点的下一个节点
free(cur); //释放当前节点
cur = next; //迭代
}
q->_front = q->_rear = NULL;
q->_size = 0;
}
3、队列——判空
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
if (q->_front == NULL) //为空
{
assert(q->_rear);
return 1;
}
else //不为空
{
return 0;
}
}
4、队列——队尾入
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->_next = NULL;
newnode->_data = data;
//队列为空
if (q->_front == NULL)
{
assert(q->_rear == NULL); //头尾都指向空
q->_front = q->_rear = newnode; //把newnode赋给头尾结构体指针
}
//队列不为空
else
{
q->_rear->_next = newnode; //链接
q->_rear = newnode; //更新尾节点
}
q->_size++;
}
5、队列——队头出
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
//一个节点
if (q->_front->_next == NULL)
{
free(q->_front); //直接释放
q->_front = q->_rear = NULL; //置空
}
//多个节点
else
{
QNode* cur = q->_front->_next; //保存头结点的下一个节点
free(q->_front); //释放当前节点
q->_front = cur; //更新头节点
}
q->_size--;
}
6、队列——获取队列队头元素
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
assert(!QueueEmpty(q)); //队列不为空
return q->_front->_data;
}
7、队列——获取队列队尾元素
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(!QueueEmpty(q)); //队列不为空
return q->_rear->_data;
}
小结
学习数据结构需要对结构体传参,结构体成员变量,结构体变量,结构体指针有着深刻地理解,如果有需要的话可以参考我的结构体基础博客里面会一一解答,下一篇博客将会对栈进行实现
最后倘若本文有遗漏疏忽,还需要你指正,以便今后改进!祝你天天开心啦!欢迎到我的博客留言,我会尽力解答,希望能给你一些帮助!