C语言队列课件

合集下载

数据结构——用C语言描述(第3版)教学课件第3章 栈和队列

数据结构——用C语言描述(第3版)教学课件第3章 栈和队列

if(S->top==-1) /*栈为空*/
return(FALSE);
else
{*x = S->elem[S->top];
return(TRUE);
}
返回主目录}[注意]:在实现GetTop操作时,也可将参数说明SeqStack *S 改为SeqStack S,也就是将传地址改为传值方式。传 值比传地址容易理解,但传地址比传值更节省时间、 空间。
返回主目录
算法:
void BracketMatch(char *str) {Stack S; int i; char ch; InitStack(&S); For(i=0; str[i]!='\0'; i++) {switch(str[i])
{case '(': case '[': case '{':
3.1.3 栈的应用举例
1. 括号匹配问题
思想:在检验算法中设置一个栈,若读入的是左括号, 则直接入栈,等待相匹配的同类右括号;若读入的是 右括号,且与当前栈顶的左括号同类型,则二者匹配, 将栈顶的左括号出栈,否则属于不合法的情况。另外, 如果输入序列已读尽,而栈中仍有等待匹配的左括号, 或者读入了一个右括号,而栈中已无等待匹配的左括 号,均属不合法的情况。当输入序列和栈同时变为空 时,说明所有括号完全匹配。
return(TRUE);
}
返回主目录
【思考题】
如果将可利用的空闲结点空间组织成链栈来管理,则申 请一个新结点(类似C语言中的malloc函数)相当于链 栈的什么操作?归还一个无用结点(类似C语言中的 free函数)相当于链栈的什么操作?试分别写出从链栈 中申请一个新结点和归还一个空闲结点的算法。

数据结构(C语言版)_第4章 栈和队列

数据结构(C语言版)_第4章 栈和队列

4.2 栈 4.2.1 栈的定义
栈(stack)是限定在表的一端进行插入或删除操 作的线性表。插入元素的操作称为入栈,删除元素的 操作称为出栈。在任何时候,都只有栈顶元素才能出 栈。换句话说,栈的修改是按先进后出、后进先出的 原则进行的,如图4-1所示。
图4-1 栈的示意图
因此,栈又称为先进后出(First In Last Out)表, 简称FILO表,或后进先出(Last In First Out)表,简称为 LIFO表。通常将允许进行插入或删除操作的一端称为栈顶 (top),被固定的另一端称为栈底(bottom)。不含数据元素的 栈称为空栈。
【拓展学习】两个栈共享同一存储空间。 在某些应用中,为了节省空间,可以让两个数据元素类型一致的 栈共享同一段一维数组空间。可以将两个栈的栈底设在存储空间 的两端,让两个栈分别向中间延伸。两个栈的栈顶变量分别为 top1、top2。只要整个存储空间未被占满,无论哪个栈的入栈都不 会发生上溢。只有两个栈的栈顶位置在中间相遇时(即 top1+1=top2)才发生上溢。因此,这种方法可以有效的提高存储 空间的利用率。我们把这种结构称为双栈,双栈如图4-7所示。
{ if (IsNull_Stack ( s ) ) return 0; /*栈空*/ else return (s->data[s->top] );
}
6. 置空栈操作 【算法4.6】置空栈 void Clear_Stack(Se_Stack *s) {
s->top=0; }
7. 求栈的长度 【算法4.7】求栈长 int StackLength(Se_Stack *s) {
第四章 栈和队列
本章要点
➢ 栈的定义和结构特点 ➢ 栈的顺序存储表示和基本操作的实现。 ➢ 栈的链式存储表示和基本操作的实现。 ➢ 队列的定义和结构特点 ➢ 队列的顺序存储表示和基本操作的实现。 ➢ 队列的链式存储表示和基本操作的实现。 ➢ 栈和队列的简单应用。

数据结构(C语言)第三章-栈和队列-讲义

数据结构(C语言)第三章-栈和队列-讲义
i 1 j 1
Cin,Cout C++的输入输出函数作用与Scanf, printf, 类似,更为简单 for (i=1; i<=3;i++) cout<<"count="<<i<<endl; count=1 count=2 count= 3
cin>>a>>b; 可以从键盘输入: 20 32.45
定义在栈结构上的基本运算
(1) (2) (3) (4) (5) (6) (7)
生成空栈操作 init_stack(s) 判栈空函数 empty_stack(s) 数据元素入栈操作 push_stack(s,x) 数据元素出栈函数 pop_stack(s) 取栈顶元素函数 gettop_stack(s) 置栈空操作 clear_stack(s) 求当前栈元素个数函数
⑵ 判空栈 Status StackEmpty ( S ) { if (S.top= = S.base) return TRUE; else return FALSE; }
⑶ 入栈 Status Push ( SqStack *S, Elemtype e) { if ( S.top-S.base >= S.stacksize ) return OVERFLOW; /*栈满不能入栈*/ else *S.top++ = e; return OK; }
例、一叠书或一叠盘子。
栈顶
a a
n n-1
取出和放入 一件物品都只能 在顶端进行。
……
a2
栈底
a1
进栈和出栈
空栈
进栈和出栈
栈顶
67

数据结构C语言版第三章 栈和队列

数据结构C语言版第三章  栈和队列

第三章栈和队列重点难点掌握栈和队列这两种抽象数据类型的特点,并能在相应的应用问题中正确选用它们;熟练掌握栈类型的两种实现方法;熟练掌握循环队列和链队列的基本操作实现算法;理解递归算法执行过程中栈的状态变化过程,便于更好地使用递归算法。

典型例题1.设将整数1,2,3,4依次进栈,但只要出栈时栈非空,则可将出栈操作按任何次序夹入其中,请回答下述问题:(1)若入、出栈次序为Push(1), Pop(),Push(2),Push(3), Pop(), Pop( ),Push(4), Pop( ),则出栈的数字序列为何(这里Push(i)表示i进栈,Pop( )表示出栈)?(2) 能否得到出栈序列1423和1432?并说明为什么不能得到或者如何得到。

(3)请分析1,2 ,3 ,4 的24种排列中,哪些序列是可以通过相应的入出栈操作得到的。

【解】(1)出栈序列为:1324(2)不能得到1423序列。

因为要得到14的出栈序列,则应做Push(1),Pop(),Push(2),Push(3),Push(4),Pop()。

这样,3在栈顶,2在栈底,所以不能得到23的出栈序列。

能得到1432的出栈序列。

具体操作为:Push(1),Pop(),Push(2),Push(3),Push(4),Pop(),Pop(),Pop()。

(3)在1,2 ,3 ,4 的24种排列中,可通过相应入出栈操作得到的序列是:1234,1243,1324,1342,1432,2134,2143,2314,2341,2431,3214,3241,3421,4321不能得到的序列是:1423,2413,3124,3142,3412,4123,4132,4213,4231,43122.循环队列的优点是什么? 如何判别它的空和满?【解】循环队列的优点是:它可以克服顺序队列的"假上溢"现象,能够使存储队列的向量空间得到充分的利用。

《数据结构(C语言)》第3章 栈和队列

《数据结构(C语言)》第3章 栈和队列
Data structures

❖ 栈的顺序存储与操作 ❖ 1.顺序栈的定义
(1) 栈的静态分配顺序存储结构描述 ② top为整数且指向栈顶元素 当top为整数且指向栈顶元素时,栈空、入栈、栈满 及出栈的情况如图3.2所示。初始化条件为 S.top=-1。
(a) 栈空S.top==-1 (b) 元素入栈S.stack[++S.top]=e (c) 栈满S.top>=StackSize-1 (d) 元素出栈e=S.stack[S.top--]
/*栈顶指针,可以指向栈顶
元素的下一个位置或者指向栈顶元素*/
int StackSize; /*当前分配的栈可使用的以 元素为单位的最大存储容量*/
}SqStack;
/*顺序栈*/
Data structures

❖ 栈的顺序存储与操作 ❖ 1.顺序栈的定义
(2) 栈的动态分配顺序存储结构描述 ① top为指针且指向栈顶元素的下一个位置 当top为指针且指向栈顶元素的下一个位置时,栈空 、入栈、栈满及出栈的情况如图3.3所示。初始化条 件为S.top=S.base。
…,n-1,n≥0} 数据关系:R={< ai-1,ai>| ai-1,ai∈D,i=1,2
,…,n-1 } 约定an-1端为栈顶,a0端为栈底 基本操作:
(1) 初始化操作:InitStack(&S) 需要条件:栈S没有被创建过 操作结果:构建一个空的栈S (2) 销毁栈:DestroyStack(&S) 需要条件:栈S已经被创建 操作结果:清空栈S的所有值,释放栈S占用的内存空间
return 1;
}
Data structures

第三章C队列

第三章C队列

//-------------------基本操作的函数原型说明 基本操作的函数原型说明---------------------基本操作的函数原型说明 Status InitQueue (LinkQueue &Q); //构造一个空队列 构造一个空队列Q 构造一个空队列 Status DestroyQueue (LinkQueue &Q); //销毁队列 ,Q不再存在 销毁队列Q, 不再存在 销毁队列 Status ClearQueue (LinkQueue &Q); //把Q清为空队列 把 清为空队列 Status QueueEmpty (LinkQueue Q); //若队列 为空队列,则返回 若队列Q为空队列 若队列 为空队列,则返回TRUE,否则返回 ,否则返回FALSE Status QueueLength (LinkQueue Q); //返回 的元素个数,即为队列的长度 返回Q的元素个数 返回 的元素个数, Status GetHead (LinkQueue Q, QElemType &e); //若队列不空 则用 返回 的队头元素 并返回 若队列不空,则用 返回Q的队头元素 并返回OK; 若队列不空 则用e返回 的队头元素,并返回 //否则返回 否则返回ERROR 否则返回 Status EnQueue (LinkQueue &Q, QElemType e); //插入元素 为Q新的队尾元素 插入元素e为 新的队尾元素 插入元素 Status DeQueue (LinkQueue &Q, QElemType &e); //若队列不空,则删除 的队头元素,用e返回其值, 若队列不空, 的队头元素, 返回其值 返回其值, 若队列不空 则删除Q的队头元素 //并返回 并返回OK;否则返回 并返回 ;否则返回ERROR Status QueueTraverse (LinkQueue Q, visit () ); //从队头到队尾依次对队列 中每个元素调用函数 从队头到队尾依次对队列Q中每个元素调用函数 从队头到队尾依次对队列 中每个元素调用函数visit(). . //一旦 一旦visit()失败,则操作失败 失败, 一旦 失败

C语言《队列》

C语言《队列》
例 A={1,2,3,4,5,6,7,8,9} R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } 可行的子集划分为: A1={ 1,3,4,8 } A2={ 2,7 } A3={ 5 } A4={ 6,9 }
Ch3_5.txt
出队算法
Ch3_6.txt
队列的算法描述
– 队列的顺序存储结构
• 实现:用一维数组实现sq[M]
rear J6 5 5 5 5 J5 4 4 4 4 J4 3 3 3 3 rear rear J3 J3 2 2 front 2 2 front rear J2 J2 1 1 1 1 front rear 0 J1 0 0 0 front J1 J4,J5,J6入队 队空 front J1,J1,J3入队 front J1,J2,J3出队 空队列条件:front==rear 入队列:sq[++rear]=x; 出队列:x=sq[++front];
front
队列的算法描述
队空:front==rear 队满:front==rear
4 3
front rear
5 2 0 1
J5 J4 front 初始状态
4 3 5 2 0 1
rear J6
J5 J4 J9 front rear
4 3 5 2 0 1
J6 J7
解决方案: 1.另外设一个标志以区别队空、队满 2.少用一个元素空间: 队空:front==rear 队满:(rear+1)%M==front
• 解决方案
– 队首固定,每次出队剩余元素向下移动——浪费时间 —— – 循环队列 » 基本思想:把队列设想成环形,让sq[0]接在sq[M-1]之 后,若rear+1==M,则令rear=0;

数据结构与算法C版课件第三章栈和队列

数据结构与算法C版课件第三章栈和队列
x成为新的栈顶元素。 (4)出栈pop(s):删除栈s的栈顶元素。 (5)读栈顶元素top(s):栈顶元素作为结果返回,
不改变栈的状态。
4.栈的存储 (1)采用顺序方式存储的栈称为顺序栈(sequential stack) (2) 采用链接方式存储的栈称为链栈(linked stack)
3.1.2 顺序栈及运算的算法实现
用栈来实现括号匹配检查的原则是,对表达式从左到右扫描。 (1)当遇到左括号时,左括号入栈; (2)当遇到右括号时,首先检查栈是否空,若栈空,则表明该“右括弧”多余;否则比 较栈顶左括号是否与当前右括号匹配,若匹配,将栈顶左括号出栈,继续操作;否则,表明 不匹配,停止操作。 (3)当表达式全部扫描完毕,若栈为空,说明括号匹配,否则表明“左括弧”有多余的。
出队
a1 a2 a3 a4 a5
入队
队列图示
4.队列的应用
5. 在队列上进行的基本运算
(1)队列初始化initQueue(q):构造一个空队列。 (2)判队空emptyQueue(q):若q为空队则返回为1,否
则返回为0。
(3)入队enQueue(q,x):对已存在的队列q,插入一个元素x
到队尾,队发生变化。
队列中元素个数的计算公式。
(4)出队deQueue(q,x):删除队头元素,并通过x返回其值,
队发生变化。
(5)读队头元素frontQueue(q):读队头元素,并返回其值,
队不变。
3.2.2 顺序队列及运算的实现
采用顺序方法存储的队列称为顺序队列(sequential queue)
顺序队列的存储结构用c语言定义如下:
#define MAXSIZE 1024
运算受限的线性 表
表两端插删
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

原因:
被删除元素的空间没有再被使用
每次出队时向前移一位置。 解决: 大量移动元素 循环队列
11
采用循环队列克服“假上溢”
sq->r
MAXNUM-1
。 。 。
0 1
sq->f
指针移动方向
12
4.5.1 顺序队列
采用循环队列克服“假上溢” 入队:if (sq->r+1>=MAXNUM) sq->r=0; else sq->r++;
3
4.5 队列的实现
4.5.1. 顺序队列 4.5.2. 链队列
4
4.5.1 顺序队列
队列的顺序存储结构简称为顺序队列。顺序队 列实际上是运算受限的顺序表。
由于队列的队头和队尾的位置均是变化的,因
而要设置两个指针,分别指示当前队头元素和队尾 元素在向量空间中的位置。
5
4.5.1 顺序队列
顺序队列的定义
进队列
EnQueue(int value) { //要先判断队列是否已满 if ((tail + 1) % QUEUE_SIZE == head) { printf("队列已满,无法从队尾插入元素\n"); } else { queue[tail] = value; tail = (tail + 1) % QUEUE_SIZE; } }
29
2. 判队空
int isEmptyQueue_seq( PSeqQueue sq ) { return (sq->f == sq->r); }
30
3. 取队头元素
DataType frontQueue_seq( PSeqQueue sq ) /* 对非空队列,求队列头部元素 */ { return (sq->q[sq->f]); }
r
k4
k5 k6 k7 k8 ③队列满
4
5 6 7 ②约定
f r
k7 k8
r
①队列空
④队列数组越界
4.5.1 顺序队列
顺序队列的入队和出队 开;data[sq->r]=x; sq->r++;
出队: sq->f++;
8
4.5.1 顺序队列
元素个数(队列长度):(sq->r) - (sq->f)
* */ int IsFull(){ if ((tail + 1) % QUEUE_SIZE == head) { printf("队列已满\n"); return 1; } printf("队列未满\n"); return 0;
}
/打印出队列元素 void PrintQueue(){ for (int i = head; i < tail; i++) { printf("%d ",queue[i]); } printf("\n"); }
39
2. 判队空(算法4.22)
int isEmptyQueue_link( PLinkQueue plqu ) {
return (plqu->f == NULL);
}
40
3. 取队头结点数据(算法4.25)
DataType frontQueue_link( PLinkQueue plqu ) /* 在非空队列中求队头元素 */ { return (plqu->f->info); }
#include<stdio.h> #define QUEUE_SIZE 200 int queue[QUEUE_SIZE]; int head=0;//头指针 int tail=0;//尾指针
int main() { EnQueue(4);EnQueue(1);EnQueue( 2);EnQueue(9);EnQueue(8); PrintQueue(); DeQueue();DeQueue(); PrintQueue(); return 0;
若(sq->r) - (sq->f)=0 ,则队列长度 为0,即空队列。再出队会“下溢”
若 (sq->r)-(sq->f)=MAXNUM,则队满。 队满时再入队会“上溢”
9
顺序队列
f r
0 1 2 3
f
k1 k2 k3
r
4
5 6 7
f r
k5 k6
队列空
队列数组越界
4.5.1 顺序队列
假上溢:当前队列并不满,但不能入队。
利用模运算 sq->r=(sq->r+1)%MAXNUM
出队: sq->f=(sq->f+1)%MAXNUM
13
4.5.1 顺序队列
判断队空和队满
某一元素出队后,若头指针已从后面追上尾指针, 则当前队列为空: sq->f=sq->r
某一元素入队后,若尾指针已从后面追上头指针, 则当前队列为满:
sq->f=sq->r
4.4 队列 队列的概念及运算(逻辑结构)
1
队列的概念
队列 只允许在表的一端进行插入,而在另一端 进行删除。 队头 队尾 允许删除的一端 允许插入的一端
队列是先进先出表
出队
a1
队头
a2
...
an
队尾
入队
2
队列的运算
队列的基本运算:

• • • •
创建一个空队列 Queue createEmptyQueue ( void ) 判队列是否为空队列 int isEmptyQueue ( Queue qu ) 往队列中插入一个元素 void enQueue ( Queue qu, DataType x ) 从队列中删除一个元素 void deQueue ( Queue qu ) 求队列头部元素的值 DataType frontQueue ( Queue qu )
an-3 . .
n-3
rear= n-1
front=n-3
an-2 n-2 . . 1 0 rear= n-1
插入元素0:1 rear 顺时针移动一位 MaxQsize-1 2
…… an-3 an-2 x
rear=0 an-3 . .
n-3
front=n-3 front=n-3
an-2 n-2 . . 1 x rear = (rear+1) MOD MaxQSize n-1
队列的链接表示
struct Node; typedef struct Node *pNode; struct Node { DataType info; pNode link; }; struct LinkQueue { PNode f; PNode r; }; typedef struct LinkQueue, *PLinkQueue;
32
5. 出队
void deQueue_seq( PSeqQueue sq ) /* 删除队列头部元素 */ { if( sq->f == sq->r ) printf( "Empty Queue.\n" ); else sq->f = (sq->f + 1) % MAXNUM;
}
33
4.5.2 链队列
31
4. 入队
void enQueue_seq( PSeqQueue sq, DataType x ) /* 在队列中插入一元素x */ { if( (sq->r + 1) % MAXNUM == sq->f ) printf( "Full queue.\n" ); else { sq->q[sq->r] = x; sq->r = (sq->r + 1) % MAXNUM; } }
k2 k3 k4 k5 k6 k1
sq.front
sq.rear
k7
图(a) 空队列
图(b) 队列满
图4.9
循环队列
4.5.1 顺序队列
在循环队列上实现五种基本运算: 1.置空队
2.判队空
3.取队头元素 4.入队 5.出队
17
循环队列
0
1 2
front= n-3
MaxQsize-1
…… an-3 an-2
/判断队列是否为空 int IsEmpty() { if (head == tail) { printf("队列为空\n"); return 1; }
printf("队列不为空\n"); return 0;
}
判断队列是否已满
/** * 我这里判断队满的的方法:
牺牲一个单元来区分队空和队满,入队时少 用一个队列单元。如果数组的大小为Size,那 么实际只能存放(Size-1)个元素。(这是比 较常用的判满的方式)
队列的链式存储结构简称为链队列,它是限制仅在 表头删除和表尾插入的单链表。
显然仅有单链表的头指针不便于在表尾做插入操作, 为此再增加一个尾指针,指向链表上的最后一个结点。 于是,一个链队列由一个头指针和一个尾指针唯一地确
定。
34
plqu f r
k0 k1 k2
….
kn-1

图4.10 队列的链接表示
0 rear=0
删除元素:front顺时针移动一位
front = (front+1) MOD MaxQSize;
. .
..
D
C
0
删除C
front=9
. .
.. 1
D rear
1 rear
相关文档
最新文档