210 likes | 366 Views
Chap3. 栈和队列. 第 3 章 栈 和队列. 3.1 栈的引例. 任一表达式都可看成是由操作数,运算符和界限符组成的一个串。其中,操作数可以是常数也可以是变量或常量的标识符,运算符可以是算术运算符,关系运算符和逻辑运算符等,界限符包括左右括号和表达式结束符等,例表达式 7+4* ( 8-3 )。计算机要完成表达式的求值,必须正确的解释表达式,将其翻译成正确的机器指令序列。要了解计算机的求值过程,必须先研究栈的性质。. 3.2 栈的定义及基本运算. 栈是限定只能在表尾进行插入和删除的线性表,并将表尾称为栈顶,表头称为栈底。 栈的基本运算如下:
E N D
Chap3 栈和队列
3.1栈的引例 任一表达式都可看成是由操作数,运算符和界限符组成的一个串。其中,操作数可以是常数也可以是变量或常量的标识符,运算符可以是算术运算符,关系运算符和逻辑运算符等,界限符包括左右括号和表达式结束符等,例表达式7+4*(8-3)。计算机要完成表达式的求值,必须正确的解释表达式,将其翻译成正确的机器指令序列。要了解计算机的求值过程,必须先研究栈的性质。
3.2栈的定义及基本运算 栈是限定只能在表尾进行插入和删除的线性表,并将表尾称为栈顶,表头称为栈底。 栈的基本运算如下: (1)判栈空Empty(S). 若栈为空则返回“真“,否则返回”假“; (2)入栈操作(压栈)Push(S,x) 将新元素压入栈中,使其成为栈顶元素; (3)出栈操作(弹栈)Pop(S,x) 若栈不空则返回栈顶元素,并从栈中删除栈顶元素,否则返回NULL; (4)取栈顶元素 Gettop(s,x) 若栈不空则返回栈顶元素,否则返回NULL; (5)置空栈Clear(s) 将当前栈设定为空栈; (6)求元素个数 CurrenSize(s) 求当前栈中元素的个数 。
3.3顺序栈的存储结构及算法实现 1.顺序栈 顺序栈利用一组连续的存储单元存放从栈底到栈顶的诸元素。 #define maxsize N typedef struct { Datatype data[maxsize+1]; int top; }Stack;
3.3顺序栈的存储结构及算法实现 2. 顺序栈的基本运算的实现 (1) 入栈操作 顺序栈的入栈操作可表示为: int Push(Stack S, Datatype x); 其中,参数S表示指定的栈,其类型为顺序栈类型Stack,参数x表示入栈的元素,其类型为元素类型Datatype。 操作的功能为在指定的栈S中插入元素x,并使x成为栈顶。 若栈不满,则从栈顶插入x并返回函数值1,否则栈的状态不变且返回函数值0。
3.3顺序栈的存储结构及算法实现 2. 顺序栈的基本运算的实现 (2)出栈操作 顺序栈的出栈操作可表示为: int Pop(Stack s, Datatype x); 其中参数s表示指定的栈,其类型为顺序栈类型Stack,该操作是一个函数,其返回值表示从栈中取出的元素。 操作的功能为若指定的栈s非空,则从s中取出栈顶元素并返回该元素,否则返回空元素NULL。
3.3顺序栈的存储结构及算法实现 2. 顺序栈的基本运算的实现 (3)取栈顶操作 顺序栈的取栈顶操作可表示为: int Gettop(Stack S, Datatype x); 其中,参数S表示指定的栈,其类型为顺序栈类型Stack,该操作是一个函数,其返回值表示从栈中取出的元素。
3.4栈的链表存储结构 3.4.1 图的相关术语 栈可以用单链表作为存储结构,链表的结点结构描述如下: typedef char ElemType; typedef struct Lsnode { ElemType data; struct Lsnode *next; } Lsnode;//结点的类型标识符 Lsnode *top;
3.4栈的链表存储结构 3.4.2 图的相关术语 1.初始化空栈 void IniStack(Lsnode *top) { top->next=NULL; } 调用此函数之前,在主调函数中(例如main( ))说明一个指针变量后,先为它申请分配一个结点,然后调用初始化函数。
3.4栈的链表存储结构 3.4.2 图的相关术语 2.入栈操作 链栈入栈操作的含义是:将一个元素推入指定的链栈中。对该操作应设置两个参数,即在参数中指定一个链栈及入栈的元素。假设指定的链栈top,入栈元素x其类型为ElemType,入栈操作取名为push,则该操作可表示为: viod Push(Lsnode *top,ElemType x) 操作的功能为在由top指向的链栈中插入元素x,使x成为栈顶元素。
3.4栈的链表存储结构 3.4.2 图的相关术语 3. 出栈操作 链栈出栈操作的含义是:从链栈中弹出栈顶结点并返回该结点中的元素值。对该操作应设置一个参数,即在参数中指定一个链栈。假设指定的链栈top,出栈操作取名为pop,则该操作可表示为: ElemType Pop(Lsnode *top) 操作的功能为从由top指向的链栈中弹出栈顶结点并返回该结点中的元素值。
3.5应用实例的实现 3.5.1 表达式中括号配对的合法性检查 在编译程序对源程序的处理过程中,常遇到括号配对的合法性检查问题。例如,在算术表达式中容许出现圆括号( )以表示表达式中运算的优先顺序,容许出现方括号[]以表示数组的下标,有些语言还容许出现花括号{ }以表示程序中的注释,但这些括号都必须配对使用。
3.6应用实例的实现 3.6.1队列的基本操作 进队算法: 根据队列的结构,若队尾指针不在队的最大长度上,则首先队尾指针加1,元素进队,否则就是队满,无法进队。 ADDQUEUE(queue,r,f,in) /* 在queue队列中进一个元素in,f和r分别是队首和队尾的标志 */ { if(r==n) { printf("队满"); } else { r++; queue[r]=in; } }
3.6应用实例的实现 3.6.1队列的基本操作 出队算法: 出队首先要判断队列中是否有元素,即R是否等于F,R=F可能出现在初态,也可能出现在出队、进队的动态变化中。 DELQUEUE(queue,r,f,out) /* 在queue队列中退出一个元素到out,f和r分别是队首和队尾的标志 */ { if(f==r) { printf("队空"); } else out=queue[++f]; }
3.6应用实例的实现 3.6.2链队的存储结构及其运算 当队空时,Front=NULL;Rear=NULL;所谓队满,是指在可利用的空间表中,所有的结点被取完,即AV=NULL时,才表示队满。根据队列的操作特点,进队和退队分别在表的两端进行,具体表现为“先进先出”。从链队的结构可看出,进队的基本操作步骤为(设进队结点的地址为x): Rear->next=x; x->next=NULL; Rear=x;
3.7栈的应用举例 编译程序对表达式进行编译时,需设置两个栈,用于存放运算符的栈称作运算符栈,简称OPS;另一个存放操作数的栈称作操作数栈,简称OVS。当编译程序自左向右对表达式进行扫描时,有如下处理规则。 1.操作数 操作数一律进入操作数栈OVS。
3.7栈的应用举例 2.运算符 (1) 若运算符栈空,运算符进入运算符栈OPS。 (2) 若运算符栈非空,则将该运算符的优先级与运算符栈OPS中的栈顶元素的优先级相比较。若该运算符的优先级大,则该运算符进OPS栈;反之,则取出OPS栈顶的运算符,并在操作数栈OVS中连续取出两个栈顶元素(操作数),与取出的运算符相运算,并将结果再存入操作数栈OVS。 (3) 进行第(2)步操作后的运算符再与运算符栈的栈顶元素的优先级比较。重复(2)步的操作,直至当前扫描到的运算符进OPS栈为止。
3.8线与队列比较 栈和队列是两种特殊的线性表,从逻辑结构上分析,其数据元素仍然是顺序存储的,数据在存储空间的存放地址也是连续的。栈的结构特点是先进后出,数据元素只能在表的一端进行插入和删除。栈指针Top始终指向栈顶元素在栈中的序号。栈的基本算法有进栈和出栈两种,在算法实现中必须注意栈满(上溢)和栈空(下溢)的判断。队列是数据元素在表的一端插入,在表的另一端删除的特殊线性表。队列的结构特点是先进先出。队列有队首指针(也称作退队指针)和队尾指针(也称作进队指针)。
本章小结 1. 掌握如下基本概念: 栈、顺序存储、链式存储、置空栈、取栈顶元素、入栈、出栈、链栈、链队列; 2.栈的顺序存储和链式存储; 3.队列的顺序存储和链式存储;