数据结构(C语言)队列
(郝斌老师视频课)
简介:
35 _ 队列1 _ 什么是队列
36 _ 队列2 _ 队列的分类和链式队列伪算法的讲解
37 _ 队列3 _ 学习循环队列必须要弄清楚的7个问题概述
38 _ 队列4 _ 静态队列为什么必须是循环队列
39 _ 队列5 _ 循环队列需要几个参数来确定及其含义的讲解
40 _ 队列6 _ 循环队列各个参数的含义
41 _ 队列7 _ 循环队列入队伪算法讲解
42 _ 队列8 _ 循环队列出队伪算法讲解
43 _ 队列9 _ 如何判断循环队列是否为空
44 _ 队列10 _ 如何判断循环队列是否已满
45 _ 复习 _ 求链表的长度【没写】
46 _ 复习上节课队列知识
47 _ 循环队列程序演示
48 _ 队列的具体应用
35 _ 队列1 _ 什么是队列
线性结构的两种常见应用之二队列
定义:
一种可以实现“先进先出”的存储结构
36 _ 队列2 _ 队列的分类和链式队列伪算法的讲解
出队:f加1,入队:r加1
队列最需要注意的是:如果有五个元素,0 1 2 3 4 位置上都有元素,f 指向的是0,r 指向的5,是有元素的下一个位置!!!
分类:
链式队列:用链表实现
静态队列:用数组实现
37 _ 队列3 _ 学习循环队列必须要弄清楚的7个问题概述
静态队列
静态队列通常都必须是循环队列
循环队列的讲解:
1)静态队列为什么必须是循环队列
2)循环队列需要几个参数来确定
3)循环队列各个参数的含义
4)循环队列入队伪算法讲解
5)循环队列出队伪算法讲解
6)如何判断循环队列是否为空
7)如何判断循环队列是否已满
38 _ 队列4 _ 静态队列为什么必须是循环队列
如果要删除元素(出队),f只能加;如果要增加元素(入队),r只能加。(按照一般数组的方法)。r指向当前队列的下一个位置。
39 _ 队列5 _ 循环队列需要几个参数来确定及其含义的讲解
需要2个参数来确定
front
rear
两个参数不同场合有不同的含义
建议初学者先记住,然后慢慢体会
1)队列初始化
front和rear的值都是零
2)队列非空
front代表的是队列的第一个元素,rear代表的是队列的最后一个有效元素的下一个元素
3)队列空
front和rear的值相等,但不一定是零
40 _ 队列6 _ 循环队列各个参数的含义
41 _ 队列7 _ 循环队列入队伪算法讲解
两步完成:
1.将值存入r所代表的位置
2.错误的写法:r=r+1;
正确写法是:r=(r+1)%数组的长度
R是5的时候就不能加1,r下一个应该是0
42 _ 队列8 _ 循环队列出队伪算法讲解
f=(f+1)%数组的长度
43 _ 队列9 _ 如何判断循环队列是否为空
如果front于rear的值相等,则该队列就一定为空。
44 _ 队列10 _ 如何判断循环队列是否已满
图1:m n f p q 图2:q r s m 都是4个元素
f 和 r 的大小没有关系。
若f、r相等,不知道队列到底是空还是满。
预备知识:
front的值可能比rear大,也可能比rear小,也可能两者相等。
如何判断循环队列是否已满
两种方式:
1.多增加一个标志参数
2.少用一个元素【通常使用第二种方式】
如何判断队列已满:如果f和r的值紧挨着,则队列已满
用C语言伪算法表示就是:
if((r+1)%数组长度==f)
已满
else
不满
45 _ 复习 _ 求链表的长度
46 _ 复习上节课队列知识
队列
定义:一种可以实现先进先出的存储结构
分类:
静态队列
链式队列(其实就是对链表操作,砍去了一些功能)
47 _ 循环队列程序演示
队列算法:
入队
出队
静态队列是一个数组,是一个循环数组,需要队首、队尾、以及数组。
typedef struct Queue
{
int *pBase; //代表的是那个数组
int front;
int rear;
}QUEUE;
1、初始化队列
初始化队列,分配一个数组,队首和队尾都是下表为0的那个位置
void init(QUEUE *pQ)
{
pQ->pBase = (int *)malloc(sizeof(int) * 6);//6个元素
//malloc动态分配6个元素的空间24个字节,malloc(sizeof(int) * 6)表示第一个字节的地址;
//(int *)表示4个字节为一个元素的空间;
//pQ->pBase 第一个元素的首地址(第一个元素占四个字节),pQ->pBase+1表示第二个元素首地址
pQ->front = 0;
pQ->rear = 0;
}
2、入队
入队时将这个元素放在r的位置,然后让r指向下一个(但是注意这里的下一个都是要用循环的)
bool full_queue(QUEUE * pQ)
{
if ((pQ->rear + 1) % 6 == pQ->front)
return true;
else
return false;
}
//如果不满,要放在r的位置,不是r的下一个位置
bool en_queue(QUEUE * pQ, int val)
{
if (full_queue(pQ))
{
return false;
}
else
{
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear + 1) % 6;
return true;
}
}
3、遍历
循环遍历输出所有数组的元素
void traverse_queue(QUEUE * pQ)
{
int i = pQ->front;
while (i != pQ->rear)
{
printf("%d ", pQ->pBase[i]);
i = (i + 1) % 6;
}
printf("\n");
}
4、出队
f 往后移动就可以,这个是循环数组,不需要释放内存什么的,后来还有可能循环回来的。
bool empty_queue(QUEUE * pQ)
{
if (pQ->front == pQ->rear)
return true;
else
return false;
}
bool out_queue(QUEUE * pQ, int * pVal) // int * pVal)目的将值传递给主函数
{
if (empty_queue(pQ))
{
return false;
}
else
{
*pVal = pQ->pBase[pQ->front];
pQ->front = (pQ->front + 1) % 6;
return true;
}
}
5、实例
#include<stdio.h>
#include<malloc.h>
typedef struct Queue
{
int *pBase; //代表的是那个数组
int front;
int rear;
}QUEUE;
void init(QUEUE *);
bool en_queue(QUEUE *, int);//入队
void traverse_queue(QUEUE *);
bool full_queue(QUEUE *);
bool out_queue(QUEUE *, int *);
bool empty_queue(QUEUE *);
int main(void)
{
QUEUE Q;
int val;
init(&Q);
en_queue(&Q, 1);
en_queue(&Q, 2);
en_queue(&Q, 3);
en_queue(&Q, 4);
en_queue(&Q, 5);
en_queue(&Q, 6);
en_queue(&Q, 7); //入队失败
traverse_queue(&Q);
if (out_queue(&Q, &val))
{
printf("出队成功,队列出队的元素是%d\n", val);
}
else
{
printf("出队失败!\n");
}
traverse_queue(&Q);
out_queue(&Q, &val);
out_queue(&Q, &val);
out_queue(&Q, &val);
out_queue(&Q, &val);
out_queue(&Q, &val);
if (out_queue(&Q, &val))
{
printf("出队成功,队列出队的元素是%d\n", val);
}
else
{
printf("出队失败!\n");
}
return 0;
}
void init(QUEUE *pQ)
{
pQ->pBase = (int *)malloc(sizeof(int) * 6);//6个元素
pQ->front = 0;
pQ->rear = 0;
}
bool full_queue(QUEUE * pQ)
{
if ((pQ->rear + 1) % 6 == pQ->front)
return true;
else
return false;
}
//如果不满,要放在r的位置,不是r的下一个位置
bool en_queue(QUEUE * pQ, int val)
{
if (full_queue(pQ))
{
return false;
}
else
{
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear + 1) % 6;
return true;
}
}
void traverse_queue(QUEUE * pQ)
{
int i = pQ->front;
while (i != pQ->rear)
{
printf("%d ", pQ->pBase[i]);
i = (i + 1) % 6;
}
printf("\n");
}
bool empty_queue(QUEUE * pQ)
{
if (pQ->front == pQ->rear)
return true;
else
return false;
}
bool out_queue(QUEUE * pQ, int * pVal) // int * pVal)目的将值传递给主函数
{
if (empty_queue(pQ))
{
return false;
}
else
{
*pVal = pQ->pBase[pQ->front];
pQ->front = (pQ->front + 1) % 6;
return true;
}
}
48 _ 队列的具体应用
所有和时间有关的操作都有队列的影子