严蔚敏版数据结构第三章.

合集下载

数据结构(严蔚敏)精第3章PPT课件

数据结构(严蔚敏)精第3章PPT课件

ppt精选版
10
二、栈的主要操作 1.初始化栈:InitStack(&S)
将栈S置为一个空栈(不含任何元素)。
2.进栈:PUSH(&S,X)
将元素X插入到栈S中,也称为 “入栈”、 “插入”、 “压 入”。
3.出栈: POP(&S,&e)
删除栈S中的栈顶元素,也称为”退栈”、 “删除”、 “弹出”。
或简单定义如下:
#define M 100 int s[M]; int top;
ppt精选版
16
图3.2 顺序栈中的进栈和出栈
Top指向栈顶元素 初态:top=-1; 空栈,栈中无元素, 进栈:top=top+1; s[top]=x; 退栈:取s[top]; top=top-1; 栈满:top=M-1;栈溢出(上溢),不能再进栈(错误状 态) top=-1时不能退栈,下溢(ppt精正选版常状态,常作控制条件17)
ppt精选版
两种存储结构中的实现都不难,但应该对它
们了如指掌,特别要注意它们的基本操作实
现时的一些特殊情况,如栈满和栈空、队满
和队空的条件以及它们的描述方法。本章要
求必须完成的算法设计题为:3.15,3.17,
3.19,3.22, 3.27 ,3.28,3.30,3.31,3.32。
其中前4个主要是练习栈的应用,后4个主要
插入:最先放入栈中元素在栈底,最后放入的元素在栈顶; 删除:最后放入的元素最先删除,最先放入的元素最后删除。 栈是一种后进先出(Last In First Out)的线性表,简称为LIFO 表。
ppt精选版
8
出栈 栈顶
an
进栈
出栈
进栈

严蔚敏 数据结构课后习题及答案解析

严蔚敏 数据结构课后习题及答案解析

第一章绪论一、选择题1.组成数据的基本单位是()(A)数据项(B)数据类型(C)数据元素(D)数据变量2.数据结构是研究数据的()以及它们之间的相互关系。

(A)理想结构,物理结构(B)理想结构,抽象结构(C)物理结构,逻辑结构(D)抽象结构,逻辑结构3.在数据结构中,从逻辑上可以把数据结构分成()(A)动态结构和静态结构(B)紧凑结构和非紧凑结构(C)线性结构和非线性结构(D)内部结构和外部结构4.数据结构是一门研究非数值计算的程序设计问题中计算机的(①)以及它们之间的(②)和运算等的学科。

①(A)数据元素(B)计算方法(C)逻辑存储(D)数据映像②(A)结构(B)关系(C)运算(D)算法5.算法分析的目的是()。

(A)找出数据结构的合理性(B)研究算法中的输入和输出的关系(C)分析算法的效率以求改进(D)分析算法的易懂性和文档性6.计算机算法指的是(①),它必须具备输入、输出和(②)等5个特性。

①(A)计算方法(B)排序方法(C)解决问题的有限运算序列(D)调度方法②(A)可执行性、可移植性和可扩充性(B)可行性、确定性和有穷性(C)确定性、有穷性和稳定性(D)易读性、稳定性和安全性二、判断题1.数据的机内表示称为数据的存储结构。

()2.算法就是程序。

()3.数据元素是数据的最小单位。

()4.算法的五个特性为:有穷性、输入、输出、完成性和确定性。

()5.算法的时间复杂度取决于问题的规模和待处理数据的初态。

()三、填空题1.数据逻辑结构包括________、________、_________ 和_________四种类型,其中树形结构和图形结构合称为_____。

2.在线性结构中,第一个结点____前驱结点,其余每个结点有且只有______个前驱结点;最后一个结点______后续结点,其余每个结点有且只有_______个后续结点。

3.在树形结构中,树根结点没有_______结点,其余每个结点有且只有_______个前驱结点;叶子结点没有________结点,其余每个结点的后续结点可以_________。

数据结构(c语言版)_严蔚敏版_第3章_栈和队列_信大(第3讲)

数据结构(c语言版)_严蔚敏版_第3章_栈和队列_信大(第3讲)

3.2.1 栈的顺序存储结构及实现 两栈共享空间
0 1 2 ……
S-1
a1 a 2 … ai
top1
top1
bj … … b2 b1
top2 top1= -1
什么时候栈1为空?
3.2.1 栈的顺序存储结构及实现 两栈共享空间
0 1 2 ……
S-1
a 1 a2 … ai
top1
什么时候栈1为空? 什么时候栈2为空?

栈的顺序存储结构简称为顺序栈,它是运算受限 的线性表。因此,可用数组来实现顺序栈。因为栈底 位置是固定不变的,所以可以将栈底位置设置在数组 的两端的任何一个端点;栈顶位置是随着进栈和退栈 操作而变化的,故需用一个整型变量top
定义:利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元 素,同时附设指针top指示栈顶元素在顺序栈中的位置。
(4)取栈顶元素操作 取出栈顶元素:先判断栈是否为空,不为 空,则将栈顶元素值取出。 出栈和取栈顶值是不同的。
3.2.1 栈的顺序存储结构及实现 (5)判栈空操作
看栈顶和栈底是否相等。 (6)置空操作 栈顶和栈底相等
3.2.1 栈的顺序存储结构及实现 两栈共享空间
在一个程序中需要同时使用具有相同数据类型的 两个栈,如何顺序存储这两个栈? 解决方案1:
3.2.2 栈的链式存储结构及实现
链栈:栈的链接存储结构 如何改造链表实现栈的链接存储?
head
a1
a2
an
将哪一端作为栈顶? 将链头作为栈顶,方便操作。 链栈需要加头结点吗? 链栈不需要附设头结点。
栈的链式存储结构称为链栈,它是运算是受限的单链表,插入和删除操作仅限制在表 头位置上进行.由于只能在链表头部进行操作,故链表没有必要像单链表那样附加头 结点。栈顶指针就是链表的头指针。

严蔚敏数据结构课后习题及答案解析

严蔚敏数据结构课后习题及答案解析

严蔚敏数据结构课后习题及答案解析数据结构课程是计算机科学与技术专业中非常重要的一门基础课程,对于学习者来说,课后习题的巩固和答案解析是学习的重要辅助材料。

本文将针对严蔚敏老师所著的《数据结构(C语言版)》中的课后习题及答案解析进行介绍和总结。

1. 第一章:绪论(略)2. 第二章:线性表(略)3. 第三章:栈和队列3.1 课后习题3.1.1 课后习题一:给定一个整数序列,请设计一个算法,其中删除整数序列中重复出现的元素,使得每个元素只出现一次。

要求空间复杂度为O(1)。

3.1.2 课后习题二:使用栈操作实现一个队列(其中队列操作包括入队列和出队列)。

3.2 答案解析3.2.1 答案解析一:我们可以使用双指针法来实现这一算法。

设定两个指针,一个指向当前元素,另一个指向当前元素的下一个元素。

比较两个元素是否相等,如果相等,则删除下一个元素,并移动指针。

如果不相等,则继续移动指针。

这样,当指针指向序列的最后一个元素时,算法结束。

空间复杂度为O(1),时间复杂度为O(n)。

3.2.2 答案解析二:使用两个栈来实现一个队列。

一个栈用于入队列操作,另一个栈用于出队列操作。

当需要入队列时,将元素直接入栈1。

当需要出队列时,判断栈2是否为空,如果为空,则将栈1中的元素逐个弹出并压入栈2中,然后从栈2中弹出栈顶元素。

如果栈2非空,则直接从栈2中弹出栈顶元素。

这样,就可以实现使用栈操作来实现队列操作。

4. 第四章:串(略)5. 第五章:数组和广义表(略)6. 第六章:树和二叉树(略)7. 第七章:图(略)通过对严蔚敏老师所著《数据结构(C语言版)》中的课后习题及答案解析的介绍,可以帮助学习者更好地理解和掌握数据结构这门课程的知识内容。

课后习题不仅可以帮助巩固所学知识,更加于提升学习者的能力和应用水平。

希望本文对于学习者们有所帮助。

(文章结束)。

严蔚敏《数据结构(c语言版)习题集》答案第三章 栈与队列

严蔚敏《数据结构(c语言版)习题集》答案第三章 栈与队列

第三章栈与队列3.15typedef struct{Elemtype *base[2];Elemtype *top[2];}BDStacktype; //双向栈类型Status Init_Stack(BDStacktype &tws,int m)//初始化一个大小为m的双向栈tws{tws.base[0]=(Elemtype*)malloc(sizeof(Elemtype));tws.base[1]=tws.base[0]+m;tws.top[0]=tws.base[0];tws.top[1]=tws.base[1];return OK;}//Init_StackStatus push(BDStacktype &tws,int i,Elemtype x)//x入栈,i=0表示低端栈,i=1表示高端栈{if(tws.top[0]>tws.top[1]) return OVERFLOW; //注意此时的栈满条件if(i==0) *tws.top[0]++=x;else if(i==1) *tws.top[1]--=x;else return ERROR;return OK;}//pushStatus pop(BDStacktype &tws,int i,Elemtype &x)//x出栈,i=0表示低端栈,i=1表示高端栈{if(i==0){if(tws.top[0]==tws.base[0]) return OVERFLOW;x=*--tws.top[0];}else if(i==1){if(tws.top[1]==tws.base[1]) return OVERFLOW;x=*++tws.top[1];}else return ERROR;return OK;}//pop3.16void Train_arrange(char *train)//这里用字符串train表示火车,'H'表示硬席,'S'表示软席{p=train;q=train;InitStack(s);while(*p){if(*p=='H') push(s,*p); //把'H'存入栈中else *(q++)=*p; //把'S'调到前部p++;}while(!StackEmpty(s)){pop(s,c);*(q++)=c; //把'H'接在后部}}//Train_arrange3.17int IsReverse()//判断输入的字符串中'&'前和'&'后部分是否为逆串,是则返回1,否则返回0{InitStack(s);while((e=getchar())!='&')push(s,e);while((e=getchar())!='@'){if(StackEmpty(s)) return 0;pop(s,c);if(e!=c) return 0;}if(!StackEmpty(s)) return 0;return 1;}//IsReverse3.18Status Bracket_Test(char *str)//判别表达式中小括号是否匹配{count=0;for(p=str;*p;p++){if(*p=='(') count++;else if(*p==')') count--;if (count<0) return ERROR;}if(count) return ERROR; //注意括号不匹配的两种情况return OK;}//Bracket_Test3.19Status AllBrackets_Test(char *str)//判别表达式中三种括号是否匹配{InitStack(s);for(p=str;*p;p++){if(*p=='('||*p=='['||*p=='{') push(s,*p);else if(*p==')'||*p==']'||*p=='}'){if(StackEmpty(s)) return ERROR;pop(s,c);if(*p==')'&&c!='(') return ERROR;if(*p==']'&&c!='[') return ERROR;if(*p=='}'&&c!='{') return ERROR; //必须与当前栈顶括号匹配}}//forif(!StackEmpty(s)) return ERROR;return OK;}//AllBrackets_Test3.20typedef struct {. int x;int y;} coordinate;void Repaint_Color(int g[m][n],int i,int j,int color)//把点(i,j)相邻区域的颜色置换为color{old=g[i][j];InitQueue(Q);EnQueue(Q,{I,j});while(!QueueEmpty(Q)){DeQueue(Q,a);x=a.x;y=a.y;if(x>1)if(g[x-1][y]==old){g[x-1][y]=color;EnQueue(Q,{x-1,y}); //修改左邻点的颜色}if(y>1)if(g[x][y-1]==old){g[x][y-1]=color;EnQueue(Q,{x,y-1}); //修改上邻点的颜色}if(x<m)if(g[x+1][y]==old){g[x+1][y]=color;EnQueue(Q,{x+1,y}); //修改右邻点的颜色}if(y<n)if(g[x][y+1]==old){g[x][y+1]=color;EnQueue(Q,{x,y+1}); //修改下邻点的颜色}}//while}//Repaint_Color分析:本算法采用了类似于图的广度优先遍历的思想,用两个队列保存相邻同色点的横坐标和纵坐标.递归形式的算法该怎么写呢?3.21void NiBoLan(char *str,char *new)//把中缀表达式str转换成逆波兰式new{p=str;q=new; //为方便起见,设str的两端都加上了优先级最低的特殊符号InitStack(s); //s为运算符栈while(*p){if(*p是字母)) *q++=*p; //直接输出else{c=gettop(s);if(*p优先级比c高) push(s,*p);else{while(gettop(s)优先级不比*p低){pop(s,c);*(q++)=c;}//whilepush(s,*p); //运算符在栈内遵循越往栈顶优先级越高的原则}//else}//elsep++;}//while}//NiBoLan //参见编译原理教材3.22int GetValue_NiBoLan(char *str)//对逆波兰式求值{p=str;InitStack(s); //s为操作数栈while(*p){if(*p是数) push(s,*p);else{pop(s,a);pop(s,b);r=compute(b,*p,a); //假设compute为执行双目运算的过程push(s,r);}//elsep++;}//whilepop(s,r);return r;}//GetValue_NiBoLan3.23Status NiBoLan_to_BoLan(char *str,stringtype &new)//把逆波兰表达式str转换为波兰式new{p=str;Initstack(s); //s的元素为stringtype类型while(*p){if(*p为字母) push(s,*p);else{if(StackEmpty(s)) return ERROR;pop(s,a);if(StackEmpty(s)) return ERROR;pop(s,b);c=link(link(*p,b),a);push(s,c);}//elsep++;}//whilepop(s,new);if(!StackEmpty(s)) return ERROR;return OK;}//NiBoLan_to_BoLan分析:基本思想见书后注释.本题中暂不考虑串的具体操作的实现,而将其看作一种抽象数据类型stringtype,对其可以进行连接操作:c=link(a,b).3.24Status g(int m,int n,int &s)//求递归函数g的值s{if(m==0&&n>=0) s=0;else if(m>0&&n>=0) s=n+g(m-1,2*n);else return ERROR;return OK;}//g3.25Status F_recursive(int n,int &s)//递归算法{if(n<0) return ERROR;if(n==0) s=n+1;else{F_recurve(n/2,r);s=n*r;}return OK;}//F_recursiveStatus F_nonrecursive(int n,int s)//非递归算法{if(n<0) return ERROR;if(n==0) s=n+1;else{InitStack(s); //s的元素类型为struct {int a;int b;}while(n!=0){a=n;b=n/2;push(s,{a,b});n=b;}//whiles=1;while(!StackEmpty(s)){pop(s,t);s*=t.a;}//while}return OK;}//F_nonrecursive3.26float Sqrt_recursive(float A,float p,float e)//求平方根的递归算法{if(abs(p^2-A)<=e) return p;else return sqrt_recurve(A,(p+A/p)/2,e);}//Sqrt_recurvefloat Sqrt_nonrecursive(float A,float p,float e)//求平方根的非递归算法{while(abs(p^2-A)>=e)p=(p+A/p)/2;return p;}//Sqrt_nonrecursive3.27这一题的所有算法以及栈的变化过程请参见《数据结构(pascal版)》,作者不再详细写出.3.28void InitCiQueue(CiQueue &Q)//初始化循环链表表示的队列Q{Q=(CiLNode*)malloc(sizeof(CiLNode));Q->next=Q;}//InitCiQueuevoid EnCiQueue(CiQueue &Q,int x)//把元素x插入循环链表表示的队列Q,Q指向队尾元素,Q->next指向头结点,Q->next->next指向队头元素{p=(CiLNode*)malloc(sizeof(CiLNode));p->data=x;p->next=Q->next; //直接把p加在Q的后面Q->next=p;Q=p; //修改尾指针}Status DeCiQueue(CiQueue &Q,int x)//从循环链表表示的队列Q头部删除元素x{if(Q==Q->next) return INFEASIBLE; //队列已空p=Q->next->next;x=p->data;Q->next->next=p->next;free(p);return OK;}//DeCiQueue3.29Status EnCyQueue(CyQueue &Q,int x)//带tag域的循环队列入队算法{if(Q.front==Q.rear&&Q.tag==1) //tag域的值为0表示"空",1表示"满"return OVERFLOW;Q.base[Q.rear]=x;Q.rear=(Q.rear+1)%MAXSIZE;if(Q.front==Q.rear) Q.tag=1; //队列满}//EnCyQueueStatus DeCyQueue(CyQueue &Q,int &x)//带tag域的循环队列出队算法{if(Q.front==Q.rear&&Q.tag==0) return INFEASIBLE;Q.front=(Q.front+1)%MAXSIZE;x=Q.base[Q.front];if(Q.front==Q.rear) Q.tag=1; //队列空return OK;}//DeCyQueue分析:当循环队列容量较小而队列中每个元素占的空间较多时,此种表示方法可以节约较多的存储空间,较有价值.3.30Status EnCyQueue(CyQueue &Q,int x)//带length域的循环队列入队算法{if(Q.length==MAXSIZE) return OVERFLOW;Q.rear=(Q.rear+1)%MAXSIZE;Q.base[Q.rear]=x;Q.length++;return OK;}//EnCyQueueStatus DeCyQueue(CyQueue &Q,int &x)//带length域的循环队列出队算法{if(Q.length==0) return INFEASIBLE;head=(Q.rear-Q.length+1)%MAXSIZE; //详见书后注释x=Q.base[head];Q.length--;}//DeCyQueue3.31int Palindrome_Test()//判别输入的字符串是否回文序列,是则返回1,否则返回0{InitStack(S);InitQueue(Q);while((c=getchar()!='@'){Push(S,c);EnQueue(Q,c); //同时使用栈和队列两种结构}while(!StackEmpty(S)){Pop(S,a);DeQueue(Q,b));if(a!=b) return ERROR;}return OK;}//Palindrome_Test3.32void GetFib_CyQueue(int k,int n)//求k阶斐波那契序列的前n+1项{InitCyQueue(Q); //其MAXSIZE设置为kfor(i=0;i<k-1;i++) Q.base[i]=0;Q.base[k-1]=1; //给前k项赋初值for(i=0;i<k;i++) printf("%d",Q.base[i]);for(i=k;i<=n;i++){m=i%k;sum=0;for(j=0;j<k;j++) sum+=Q.base[(m+j)%k];Q.base[m]=sum; //求第i项的值存入队列中并取代已无用的第一项printf("%d",sum);}}//GetFib_CyQueue3.33Status EnDQueue(DQueue &Q,int x)//输出受限的双端队列的入队操作{if((Q.rear+1)%MAXSIZE==Q.front) return OVERFLOW; //队列满avr=(Q.base[Q.rear-1]+Q.base[Q.front])/2;if(x>=avr) //根据x的值决定插入在队头还是队尾{Q.base[Q.rear]=x;Q.rear=(Q.rear+1)%MAXSIZE;} //插入在队尾else{Q.front=(Q.front-1)%MAXSIZE;Q.base[Q.front]=x;} //插入在队头return OK;}//EnDQueueStatus DeDQueue(DQueue &Q,int &x)//输出受限的双端队列的出队操作{if(Q.front==Q.rear) return INFEASIBLE; //队列空x=Q.base[Q.front];Q.front=(Q.front+1)%MAXSIZE;return OK;}//DeDQueue3.34void Train_Rearrange(char *train)//这里用字符串train表示火车,'P'表示硬座,'H'表示硬卧,'S'表示软卧,最终按PSH的顺序排列{r=train;InitDQueue(Q);while(*r){if(*r=='P'){printf("E");printf("D"); //实际上等于不入队列,直接输出P车厢 }else if(*r=='S'){printf("E");EnDQueue(Q,*r,0); //0表示把S车厢从头端入队列}else{printf("A");EnDQueue(Q,*r,1); //1表示把H车厢从尾端入队列}}//whilewhile(!DQueueEmpty(Q)){printf("D");DeDQueue(Q);}//while //从头端出队列的车厢必然是先S后H的顺序}//Train_Rearrange。

严蔚敏数据结构各章习题及答案

严蔚敏数据结构各章习题及答案

数据结构习题及解答第1章 概述【例1-1】分析以下程序段的时间复杂度。

for(i=0;i<n;i++) for(j=0;j<m;j++) A[i][j]=0;解:该程序段的时间复杂度为O (m*n )。

【例1-2】分析以下程序段的时间复杂度。

i=s=0; ① while(s<n) { i++; ② s+=i; ③ }解:语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O (1)。

语句②和语句③构成while 循环语句的循环体,它们的执行次数由循环控制条件中s 与n 的值确定。

假定循环重复执行x 次后结束, 则语句②和语句③各重复执行了x 次。

其时间复杂度按线性累加规则为O (x )。

此时s 与n 满足关系式:s ≥n ,而s=1+2+3+…+x 。

所以有:1+2+3+…+x ≥n ,可以推出:x=nn 241212811+±-=+±-x 与n 之间满足x=f(n ),所以循环体的时间复杂度为O (n ),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O (n )。

【例1-3】分析以下程序段的时间复杂度。

i=1; ① while(i<=n) i=2*i; ②解:其中语句①的执行次数是1,设语句②的执行次数为f (n ),则有:n n f ≤)(2。

得:T(n)=O(n2 log)【例1-4】有如下递归函数fact(n),分析其时间复杂度。

fact(int n){ if(n<=1)return(1);①elsereturn(n*fact(n-1));②}解:设fact(n)的运行时间函数是T(n)。

该函数中语句①的运行时间是O(1),语句②的运行时间是T(n-1)+ O(1),其中O(1)为常量运行时间。

由此可得fact(n)的时间复杂度为O(n)。

习题1一、单项选择题1.数据结构是指(1. A )。

A.数据元素的组织形式B.数据类型C.数据存储结构D.数据定义2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2. C )。

严蔚敏版数据结构课后习题答案-完整版

严蔚敏版数据结构课后习题答案-完整版

2n
2
,g
n
n n2
n5
解: (1)g(n) 快 (2)g(n) 快 (3)f(n) 快 (4) f(n) 快
1.15 试用数学归纳法证明:
n
(1)
i 2 n n 1 2n 1 / 6
i1
n0
n
(2)
xi
i0
xn 1 1 / x 1
x 1, n 0
n
(3)
2i 1 2n 1
i1
n1
n
(4)
2i 1 n 2
(2) 以函数的返回值判断正确与否常用于子程序的测试,便于实 现程序的局部控制。
(3) 用整型函数进行错误处理的优点是可以给出错误类型,便于 迅速确定错误。 1.7 在程序设计中,可采用下列三种方法实现输出和输入:
(1) 通过 scanf 和 printf 语句; (2) 通过函数的参数显式传递; (3) 通过全局变量隐式传递。 试讨论这三种方法的优缺点。
解:(1) 用 scanf 和 printf 直接进行输入输出的好处是形象、 直 观,但缺点是需要对其进行格式控制,较为烦琐,如果出现错误,则 会引起整个系统的崩溃。
(2) 通过函数的参数传递进行输入输出,便于实现信息的隐蔽, 减少出错的可能。
(3) 通过全局变量的隐式传递进行输入输出最为方便,只需修改 变量的值即可,但过多的全局变量使程序的维护较为困难。 1.8 设 n 为正整数。试确定下列各程序段中前置以记号 @的语句的频 度:
i1
n1
1.16 试写一算法,自大至小依次输出顺序读入的三个整数 X,Y 和 Z
的值
解:
int max3(int x,int y,int z)
{

严蔚敏数据结构课件chap3(2)

严蔚敏数据结构课件chap3(2)

Status EnQueue (SqQueue &Q, QElemType e) { // 插入元素e为Q的新的队 尾元素 if ((Q.rear+1) % MAXQSIZE == Q.front) return ERROR; //队列满 Q.base[Q.rear] = e; Q.rear = (Q.rear+1) % MAXQSIZE; return OK; }
1 2 3 返址 n
5 7 5 8
a z
一、 抽象数据类型队列的定义 链队列---队列的链式表示 二、 链队列 队列的链式表示 和实现 循环队列---队列的顺序表 三、 循环队列 队列的顺序表 示和实现
队列的类型定义
ADT Queue { 数据对象: 数据对象: D={ai | ai∈ElemSet, i=1,2,...,n, n≥0} 数据关系: 数据关系: R1={ <a i-1,ai > | ai-1, ai ∈D, i=2,...,n} 约定其中a1 端为队列头 an 端为队列尾 队列头, 队列头 队列尾 基本操作: 基本操作: } ADT Queue
队列的基本操作: 队列的基本操作:
InitQueue(&Q) QueueEmpty(Q) GetHead(Q, &e) EnQueue(&Q, e) DestroyQueue(&Q) QueueLength(Q) ClearQueue(&Q) DeQueue(&Q, &e)
QueueTravers(Q, visit())

}// a
递归函数执行的过程可视为同一函数 同一函数 进行嵌套调用,例如:
递归工作栈: 递归工作栈:递归过程执行过程中占用的
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
8
顺序栈的基本运算:
• 判栈空 • int StackEmpty (SeqStack *S) { • if( S->top == S->base ) return 1 //空则返回1 else return 0; //否则返回0 • } • 判栈满 • int StackFull (SeqStack *S) { • if( S->top- S->base >= S-> StackSize ) return 1 //判栈满,满则返回1 • else return 0; //否则返回0 • } 9
―进” =压入=PUSH(x) ―出” =弹出=POP ( y )
4
教材P44对栈有更详细定义:
栈 是仅在表尾进行插入、删除操作的线性表。 表尾(即 an 端)称为栈顶 top ; 表头(即 a1 端)称为栈底base 例如: 栈 s= (a1 , a2 , a3
, ……….,an-1 ,
an ) an 称为 栈顶元素
顺序栈中的PUSH函数 status Push(ElemType x) { if(top>M){上溢} else v[top++]=x; }
12
• 入栈 • int Push (SeqStack *S, StackData x) { • //插入元素x为新的栈顶元素 • if ( StackFull (S) ){ • S->base =( StackData *)malloc(S->base , • (S->stacksize+ STACKINCREMENT) * sizeof(StackData)); • if(! S->base)exit(overflow); • S->top= S->base + S->stacksize; • S->stacksize+= STACKINCREMENT; //追加存储空间 • } • *(S->top)=x; • (S->top)++; • Return ok • } 13
3. 存储结构
4. 运算规则
5. 实现方式
基本操作有入栈、出栈、读栈顶元素值、建 栈、或判断栈满、栈空等。
3
3.1 栈
问:堆栈是什么?它与一般线性表有什么不同?
答:堆栈是一种特殊的线性表,它只能在表的一端 (即栈顶)进行插入和删除运算。 与一般线性表的区别:仅在于运算规则不同。
一般线性表 逻辑结构:一对一 存储结构:顺序表、链表 运算规则:随机存取 堆栈 逻辑结构:一对一 存储结构:顺序栈、链栈 运算规则:后进先出(LIFO)
出栈操作——例如从栈中取出‘B‘ (注意要遵循“后进先出” 原则)
高地址M
top D C B A
低地址L
D top C B A
D C B A
D top C B A
top
核心语句: Pop ( ); Pop ( ); Printf( Pop () );
顺序栈中的POP函数 status Pop( ) { if(top=L) { 下溢 } else { y=v[--top]; return(y);} }
top base top base
top
a a 进栈
base
b a
空栈
b 进栈
6
顺序栈示意图
data
s
top
99 . . . 3 2 1 0
(栈顶)
a3 a2 a1
(栈底)
顺序栈的类型表示:
• #define STACK_INIT_SIZE 100; • #define STACKINCREMENT 10; • typedef char StackData; • typedef struct { //顺序栈定义 • StackData *base; //栈底指针 • StackData *top; //栈顶指针 • int stacksize;//当前已分配的存储空间 • } SeqStack;
Return ok;
}
10
表和栈的操作区别——对线性表 s= (a1 , a2 顺序表V[n]高地址,ຫໍສະໝຸດ …. , an-1 ,an )
表尾 an ……
高地址
顺序栈S an+1 an ……
ai …… a2 a1
栈顶top
v[i]
ai ……
低地址
a2 a1
表头
低地址
栈底base
写入:v[i]= ai 读出: x= v[i]
数据结构课程的内容
1
第三章 栈和队列
3.1 栈(Stack) 3.2 队列(Queue)
1. 定义 2. 逻辑结构 3. 存储结构 4. 运算规则 5. 实现方式 1. 定义 2. 逻辑结构 3. 存储结构 4. 运算规则 5. 实现方式
2
3.1 栈
1. 定义
2. 逻辑结构
限定只能在表的一端进行插入和删除运算的 线性表(只能在栈顶操作) 与同线性表相同,仍为一对一关系。 用顺序栈或链栈存储均可,但以顺序栈更常见 只能在栈顶运算,且访问结点时依照后进先出 (LIFO)或先进后出(FILO)的原则。 关键是编写入栈和出栈函数,具体实现依顺 序栈或链栈的不同而不同。
初始化
void InitStack ( SeqStack *S) { //置空栈
S->base =( StackData *)malloc(STACK_INIT_SIZE * sizeof(StackData)); if (!S->base) exit(OVERFLOW); S->top = S->base ; S->stacksize= STACK_INIT_SIZE ;
压入:PUSH (an+1) 弹出: POP (x) 前提:一定要预设栈顶指针top!
11
入栈操作——例如用堆栈存放(A,B,C,D) (注意要遵循“后进先出” 原则)
高地址M
低地址L
top A
B top A
top C B A
top
D C B A
top
核心语句: top=L; Push (A); Push (B); Push (C); Push (D);
a1 称为 栈底元素
插入元素到栈顶(即表尾)的操作,称为入栈。 从栈顶(即表尾)删除最后一个元素的操作,称为出栈。
强调:插入和删除都只能在表的一端(栈顶)进行!
5
栈的表示和实现
• 顺序栈:栈的顺序存储结构,利用一组地 址连续的存储单元依次存放自栈底到栈顶 的数据元素,指针top指向栈顶元素在顺 序栈中的下一个位置, • base为栈底指针,指向栈底的位置。
相关文档
最新文档