实用数据结构基础
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(2)入队 int InQueue ( csequeue *q ,datatype x) { if (n= =MAXLEN) 队满" { printf ("队满"); 队满不能入队,返回0 return 0; // 队满不能入队,返回0 } else >rear=(q->rear+1 MAXLEN; { q->rear=(q->rear+1) % MAXLEN; >data[q->rear]=x; q->data[q->rear]=x; >n++; q->n++; 入队完成,返回1 return 1; // 入队完成,返回1 } }
第 4 章 目录
4-1 队列的定义和基本运算 4-2 队列的存储及运算的实现 4-3 队列的应用举例 小 结 实验4 实验 队列子系统 习题4 习题
4 -1
队列的定义和基本运算
4-1-1 队列(Queue)的定义 队列( )
1.队列的定义 . 设有n个元素的队列 ( 则称a 设有 个元素的队列Q=(a1,a2,a3,…,an),则称 1 个元素的队列 , 为队尾元素. 队列中的元素按, 为队首元素 , an 为队尾元素 . 队列中的元素按 , a1 , a2 , a3,…,an–1 ,an的次序进队,按a 1,a2,a3,…,an–1 ,an 的次序进队, , , 次序出队,即队列的操作是按照"先进先出" 的原则进行的. 次序出队,即队列的操作是按照"先进先出" 的原则进行的. 2. 队列的特性 (1)队列的主要特性是"先进先出". )队列的主要特性是"先进先出" (2)队列是限制在两端进行插入和删除操作的线性表. )队列是限制在两端进行插入和删除操作的线性表. 队尾( 能够插入元素的一端称为 队尾(Rear),允许删除元素 ) 队首( 的一端称为 队首(Front). )
实用数据结构基础
第4章 队列
第4章 队列
知识点
队列的定义和特点 队列的存储实现及运算实现 队列的应用举例
难点
循环队列的特点及判断溢出的条件 利用队列的特点设计相关的应用问题
要求 熟练掌握以下内容: 熟练掌握以下内容:
队列的特点和基本运算 循环队列的特征和基本运算
了解以下内容: 了解以下内容:
队列运算的时间复杂性分析 队列的实际应用
(3)出队 int Outsequeue (csequeue *q ,datatype *x) {if (n= =0) 队空" {printf ("队空"); 队空不能出队,返回0 return 0; // 队空不能出队,返回0 } else >front=(q->front+1 MAXLEN; { q->front=(q->front+1) % MAXLEN; x=q->data[q->front]; *x=q->data[q->front]; // 读出队头元素 q->n – –; ; 出队完成,返回1 return 1; // 出队完成,返回1 } }
4-1-2 队列的基本运算
(1)入队操作: InQueue(q,x) )入队操作: ( , ) 初始条件: 存在且未满. 初始条件:队q存在且未满. 存在且未满 操作结果:输入一个元素x到队尾 长度加1. 到队尾, 操作结果:输入一个元素 到队尾,长度加 . (2)出队操作: OutQueue(q,x) )出队操作: ( , ) 初始条件: 存在, 初始条件 队q存在,且非空. 存在 且非空. 操作结果:删除队首元素,长度减1. 操作结果:删除队首元素,长度减 . (3)读队头元素:ReadFront(q,x) )读队头元素: ( , ) 初始条件: 存在且非空. 初始条件: 队q存在且非空. 存在且非空 操作结果: 读队头元素,队列不变. 操作结果: 读队头元素,队列不变.
图4-2
rear=7
rear=9
H G F
rear=4
J I H G F
E D C B A
(b)
front=4
front=4
Rear=-1 front=-1 (a)
front=-1 (c) (d)
ห้องสมุดไป่ตู้
从示意图中可以看到,随着入队,出队操作的进行, 从示意图中可以看到,随着入队,出队操作的进行,整 个队列会整体向后移动,这样就出现了图4 个队列会整体向后移动 , 这样就出现了图 4-2 ( d ) 中的现 队尾指针虽然已经移到了最后, 象 : 队尾指针虽然已经移到了最后 , 而队列却未真满的 假溢出"现象,使得队列的空间没有得到有效的利用. "假溢出"现象,使得队列的空间没有得到有效的利用.
(4)显示队列中元素 )显示队列中元素ShowQueue (q) ) 初始条件: 队列q存在 且非空. 存在, 初始条件: 队列 存在,且非空. 操作结果: 显示队列中所有元素. 操作结果: 显示队列中所有元素. (5)判队空操作:QEmpty(q) )判队空操作: ( ) 初始条件: 存在. 初始条件: 队q存在. 存在 操作结果: 若队空则返回为0,否则返回为1. 操作结果: 若队空则返回为 ,否则返回为 . (6)判队满操作:QFull(q) )判队满操作: ( ) 初始条件: 存在. 初始条件: 队q存在. 存在 操作结果: 若队满则返回为0,否则返回为1. 操作结果: 若队满则返回为 ,否则返回为 . (7)求队列长度 )求队列长度Qlen(q) ( ) 初始条件: 队列q存在 存在. 初始条件: 队列 存在. 操作结果: 返回队列的长度. 操作结果: 返回队列的长度.
循环队列的结构体类型定义如下: 循环队列的结构体类型定义如下:
typedef struct data[MAXLEN] [MAXLEN]; {datatype data[MAXLEN]; front,rear; int front,rear; int n; }csequeue; }csequeue;
出队
入队
a1 a2 a3 a4 a5 … … an
图4-1 队列示意图
4. 队列的实例
(1)如车站排队买票或自动取款机排队取款. )如车站排队买票或自动取款机排队取款. (2)在计算机处理文件打印时,为了解决高速的 )在计算机处理文件打印时,为了解决高速的CPU与低 与低 速的打印机之间的矛盾,对于多个请求打印文件, 速的打印机之间的矛盾 , 对于多个请求打印文件 , 操作系 统把它们当作可以被延迟的任务, 统把它们当作可以被延迟的任务 , 提出打印任务的先后顺 就是它们实际打印的先后顺序. 即按照" 先进先出" 序 , 就是它们实际打印的先后顺序 . 即按照 " 先进先出 " 的原则形成打印队列. 的原则形成打印队列.
若在( 的情况下, 相继出队, 此时队空, 若在 ( a ) 的情况下 , a6~a9 相继出队 , 此时队空 , front=8, rear=8,如 ( c ) 所示,也有:front= =rear, front=8 rear=8 所示, 也有: =rear, 也 就 是 说 , 仅 根 据 等 式 front= =rear 无 法 有 效 判 别 是 队满"还是"队空" "队满"还是"队空". 两种常用的方法: 两种常用的方法: (1)规定:当front= =rear,表示循环队列为空; =rear,表示循环队列为空; 规定: rear+1 MAXLEN,表示循环队列为满. 当front= =(rear+1)% MAXLEN,表示循环队列为满. ( 2 )在定义结构体时,附设一个存储循环队列中元素个 在定义结构体时, 数的变量n 时表示队空; 数的变量n,当n= =0时表示队空; =MAXLEN时为队满 时为队满. 当n= =MAXLEN时为队满.
顺序队可以用C++语言定义: 语言定义: 顺序队可以用 语言定义
#define MAXLEN 10 // 队列的最大容量 typedef struct {datatype Q[MAXLEN]; // datatype 可根据用户需要定义 ; int front= –1, rear= –1; // 定义队头,队尾指针,并置队列为空 ; 定义队头,队尾指针, }Queue; ; Queue *p; ; // 定义一个指向队的指针变量 p=new Queue; // 申请一个顺序队的存储空间 ;
// 在C中用 = malloc(sizeof(Queue)) 中用p 中用 ( ( ))
设: 队头指针: 队头指针:p->front 队尾指针: 队尾指针:p->rear
指向队头元素前面一个位置 指向队尾元素. 指向队尾元素.
(1)判队空 ) 时表示队空. 当p->front = p->rear= –1时表示队空.如图 (a) 时表示队空 如图4-2( ) (2)入队 ) 在无溢出的情况下,队尾指针加1,新元素即可入队: 在无溢出的情况下,队尾指针加 ,新元素即可入队: p->rear++; // 先将队尾指针加 先将队尾指针加1 ; p->Q[p->rear]=x; // 入队 ; (3)出队. )出队. 在队列非空的情况下允许出队,出队时队头指针加1, 在队列非空的情况下允许出队,出队时队头指针加 , 队头元素即可输出: 队头元素即可输出: p->front++; ; x=p->Q[p->front]; // 队头元素送x ; (4)队列的长度: m= (p->rear)–(p->front); )队列的长度: ; (5)判队满: m= MAXLEN; )判队满: ; 判队空: 判队空: m=0 .
2.循环队列
为了解决上述队列的"假溢出"现象,要做移动操作, 为了解决上述队列的"假溢出"现象,要做移动操作, 当移动数据较多时将会影响队列的操作速度. 当移动数据较多时将会影响队列的操作速度 . 一个更有效 的方法是将队列的数据区Q[ ..MAXLEN Q[0 MAXLEN的方法是将队列的数据区Q[0 ..MAXLEN-1]看成是首尾相连 Q[0 的 环 , 即 将 表 示 队 首 的 元 素 Q[0] 与 表 示 队 尾 的 元 素 Q[MAXLEN–1 连接起来,形成一个环形表, Q[MAXLEN 1]连接起来,形成一个环形表,这就成了循环队 列,如图4-3所示. 如图4 所示.
// 定义数据的类型及数据的存储区 定义队头, // 定义队头,队尾指针 // 用以记录循环队列中元素的个数 // 循环队列变量名
3. 循环队列的基本运算
(1)置空队 ) csequeue* IniQueue ( ) { q=new csequeue ; 语言中用malloc (sizeof (csequeue) ) // 在c语言中用 q->front=q->rear=MAXLEN-1; ; q->n=0; ; return q; ; }
4 -2
队列的存储实现及运算实现
4-2-1 顺序队列
1.顺序队列 .
顺序队列是用内存中一组连续的存储单元顺序存放队 列中各元素. 所以可以用一维数组Q[MAXLEN]作为队列 列中各元素 . 所以可以用一维数组 作为队列 的顺序存储空间,其中MAXLEN为队列的容量,队列元素 为队列的容量, 的顺序存储空间,其中 为队列的容量 单元开始存放, 单元. 从 Q[0]单元开始存放 , 直到 单元开始存放 直到Q[MAXLEN–1]单元 . 因为队 单元 头和队尾都是活动的,因此,除了队列的数据以外, 头和队尾都是活动的, 因此 , 除了队列的数据以外, 一般 还设有队首( 还设有队首(front)和队尾(rear)两个指针. )和队尾( )两个指针.
MAXLEN-1
图4-3 循环队列示意图
图4-4是假设长度为10的循环队列操作示意图. 是假设长度为10的循环队列操作示意图. 10的循环队列操作示意图 因为是头尾相接的循环结构, 因为是头尾相接的循环结构 , 所以将入队时的队尾指 针加1操作修改为: 针加1操作修改为: (p->rear+1 MAXLEN; p->rear= (p->rear+1) % MAXLEN; 将出队时的队头指针加1操作修改为: 将出队时的队头指针加1操作修改为: (p->front+1 MAXLEN; p->front= (p->front+1) % MAXLEN; 在图4 此时front= front=4 rear=8 队列中具有: 在图4-4(a)中,此时front=4,rear=8,队列中具有 四个元素; a6 ,a7 ,a8,a9四个元素; 随着a 相继入队, front=4 rear=4 随着 a10~a15 相继入队 , 此时 front=4 , rear=4 , 队列 已满, 已满,如(b)所示,可见在队满情况下有: 所示,可见在队满情况下有: =rear. front= =rear.