ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:122.26KB ,
资源ID:15651909      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-15651909.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(本章主要内容1栈的概念存储结构及其基本操作及其应用2.docx)为本站会员(b****7)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

本章主要内容1栈的概念存储结构及其基本操作及其应用2.docx

1、本章主要内容1栈的概念存储结构及其基本操作及其应用2本章主要内容:1、栈的概念、存储结构及其基本操作及其应用;2、队列的概念、存储结构及其基本操作及其应用课时分配:1、2各占2学时,上机2学时重点、难点:栈的存储结构及其基本操作、队列存储结构及其基本操作3.1 栈3.1.1 栈的定义栈是一种特殊的线性表。其特殊性在于限定插入和删除数据元素的操作只能在线性表的一端进行。如下所示:结论:后进先出(Last In First Out),简称为LIFO线性表。例31:家里吃饭的碗,通常在洗干净后一个一个地落在一起存放,在使用时,若一个一个地拿,一定最先拿走最上面的那只碗,而最后拿出最下面的那只碗。例3

2、2:在建筑工地上,使用的砖块从底往上一层一层地码放,在使用时,将从最上面一层一层地拿取。下面我们先给出栈结构的基本操作:(1)初始化栈 InitStack(S) (2)入栈 Push(S,elem) (3)出栈 Pop(S,elem) (4)获取栈顶元素内容 GetTop(S,elem) (5)判断栈是否为空 StackEmpty(S) 3.1.2 栈的顺序存储结构及其基本运算的实现栈的顺序存储结构是用一组连续的存储单元依次存放栈中的每个数据元素,并用起始端作为栈底。类型定义如下所示:#define MAXSIZE 100#define ERROR -1typedef struct /* 栈类

3、定义 */ int elementsMAXSIZE; int top; Stack;基本操作算法:(1)初始化栈void InitStack( Stack *S ) /* 初始化栈,将栈置空 */ S-top = 0;(2)入栈 void Push(Stack *S, int x) /* 将元素x压入到栈S中 */ if( !IsFull(*S) ) /* 如果尚未达到栈满,则将x压入栈S中,并使栈顶指针增1 */ S-elementsS-top = x; S-top+; else printf( 栈上溢!n );(3)出栈 int Pop( Stack *S ) /* 将栈S中的栈顶元素出栈

4、 */ if( !IsEmpty( *S ) ) /* 如果栈非空,则返回栈顶元素,并使栈顶指针减1 */ S-top-; return S-elementsS-top; else printf( 栈下溢!n ); return ERROR; (4)获取栈顶元素内容 int GetTop( Stack S ) /* 获取栈顶元素,但不改变栈顶指针 */ if( !IsEmpty( S ) ) return S.elementsS.top-1; else printf( 栈空!n ); return ERROR; (5)判断栈S是否为空bool IsEmpty( Stack S) /* 判断栈是

5、否为空。如果栈空,返回true,否则返回false */ if( S.top = 0 ) return true; else return false;结论:由于栈的插入和删除操作具有它的特殊性,所以用顺序存储结构表示的栈并不存在插入删除数据元素时需要移动的问题,但栈容量难以扩充的弱点仍就没有摆脱。3.1.3 栈的链式存储及其基本运算的实现 若是栈中元素的数目变化范围较大或不清楚栈元素的数目,就应该考虑使用链式存储结构。人们将用链式存储结构表示的栈称作链栈。链栈通常用一个无头结点的单链表表示。如图示:结点类型定义:typedef struct node /* 栈类定义 */ int data;

6、 struct node *next; LinkStack;(1)初始化void InitLinkStack( LinkStack *top ) /* 初始化栈,将栈置空 */ *top = NULL;(2)判断是否为空bool IsEmpty( LinkStack *top) /* 判断栈是否为空。如果栈空,返回true,否则返回false */ if( top = NULL ) return true; else return false;(3)进栈void Push(LinkStack *top, int x) /* 将元素x压入到栈S中,先申请结点再将其入栈 */ LinkStack

7、*S; S = (LinkStack *)malloc( sizeof(LinkStack) ); S-data = x; S-next = *top; *top = S;(4)出栈int Pop( LinkStack *top ) /* 将栈S中的栈顶元素出栈 */ LinkStack *S; int data; if( !IsEmpty( *top ) ) /* 如果栈非空,则返回栈顶元素,并使栈顶指针减1 */ S = *top; *top = (*top)-next; data = S-data; free( S ); return data; else printf( 栈下溢!n )

8、; return ERROR; (5)取栈顶元素int GetTop( LinkStack *top ) /* 获取栈顶元素,但不改变栈顶指针 */ if( !IsEmpty( top ) ) return top-data; else printf( 栈空!n ); return ERROR; (6)清空void EmptyLinkStack( LinkStack *top ) /* 清空堆栈S,使其栈顶指针为0 */ LinkStack *S; while( *top != NULL ) S = (*top)-next; free( *top ); *top = S; 3.1.4 栈的应用

9、举例例3-3: 将从键盘输入的字符序列逆置输出比如,从键盘上输入:tset a si sihT;算法将输出:This is a test下面我们给出解决这个问题的完整算法。typedef char Elemtype;void ReverseRead( ) Stack S; /定义一个栈结构Schar ch; InitStack(&S); /初始化栈while (ch=getchar()!=n) /从键盘输入字符,直到输入换行符为止Push(&S ,ch); /将输入的每个字符入栈while (!StackEmpty(S) /依次退栈并输出退出的字符Pop(&S,&ch);putchar(ch)

10、;putchar(n);例34: 十进制数值转换成二进制 使用展转相除法将一个十进制数值转换成二进制数值。即用该十进制数值除以2,并保留其余数;重复此操作,直到该十进制数值为0为止。最后将所有的余数反向输出就是所对应的二进制数值。比如:(692)10 = (1010110100)2,其展转相除的过程如图所示:下面给出解决这个问题的完整算法。void Decimal _ Binary ( )STACK S; /定义栈结构S InitStack(&S); /初始化栈Sscanf(%d,data); /输入十进制正整数while (data) Push(&S,data%2); /余数入栈data/=

11、2; /被除数data整除以2,得到新的被除数while (!StackEmpty(S) /依次从栈中弹出每一个余数,并输出之Pop(&S,&data); printf(%d,data);例35: 检验表达式中的括号匹配情况 假设在一个算术表达式中,可以包含三种括号:圆括号(和),方括号和和花括号和,并且这三种括号可以按任意的次序嵌套使用。比如,.(.).。现在需要设计一个算法,用来检验在输入的算术表达式中所使用括号的合法性。算术表达式中各种括号的使用规则为:出现左括号,必有相应的右括号与之匹配,并且每对括号之间可以嵌套,但不能出现交叉情况。我们可以利用一个栈结构保存每个出现的左括号,当遇到右

12、括号时,从栈中弹出左括号,检验匹配情况。在检验过程中,若遇到以下几种情况之一,就可以得出括号不匹配的结论。(1)当遇到某一个右括号时,栈已空,说明到目前为止,右括号多于左括号;(2)从栈中弹出的左括号与当前检验的右括号类型不同,说明出现了括号交叉情况;(3)算术表达式输入完毕,但栈中还有没有匹配的左括号,说明左括号多于右括号。下面是解决这个问题的完整算法。typedef char Elemtype;int Check( )STACK S; /定义栈结构Schar ch; InitStack(&S); /初始化栈Swhile (ch=getchar()!=n) /以字符序列的形式输入表达式swi

13、tch (ch) case (ch=(|ch= |ch= ): Push(&S,ch);break; /遇左括号入栈/在遇到右括号时,分别检测匹配情况case (ch= ): if (StackEmpty(S) retrun FALSE; else Pop(&S,&ch);if (ch!= () return FALSE; break;case (ch= ): if (StackEmpty(S) retrun FALSE;else Pop(&S,&ch);if (ch!= ) return FALSE; break;case (ch= ): if (StackEmpty(S) retrun F

14、ALSE;else Pop(&S,&ch);if (ch!= ) return FALSE; break;default:break;if (StackEmpty(S) return TRUE;else return FALSE;3.2 队列3.2.1 队列的定义插入端和删除端都是浮动的。通常我们将插入端称为队尾,用一个队尾指针指示;而删除端被称为队头,用一个队头指针指示。结论:先进先出(First In First Out),简称为FIFO线性表。例3-6:到医院看病,首先需要到挂号处挂号,然后,按号码顺序救诊。例3-7:乘坐公共汽车,应该在车站排队,车来后,按顺序上车。例3-8:在Wind

15、ows这类多任务的操作系统环境中,每个应用程序响应一系列的消息,像用户点击鼠标; 拖动窗口这些操作都会导致向应用程序发送消息。为此,系统将为每个应用程序创建一个队列,用来存放发送给该应用程序的所有消息,应用程序的处理过程就是不断地从队列中读取消息,并依次给予响应。下面我们给出队列结构的基本操作:(1)初始化队列 InitQueue(Q) (2)入队 EnQueue(Q,elem) (3)出队 DeQueue(Q,elem) (4)获取队头元素内容 GetFront(Q,elem) (5)判断队列是否为空 QueueEmpty(Q)3.2.2 队列的顺序存储结构及其基本运算的实现队列的顺序存储结

16、构如下图所示:012n-2n-1a1a2a3an-1an问题1:当队列空时,对头和队尾指针都为1,队列将变成下图所示状态:012n-2n-1问题2:假溢出,即,在添加数据时,可能出现没有剩余空间而实际队列又不满的状况。如:01234567a5a6a7a8rearfront解决办法:将存储队列元素的一维数组首尾相接形成一个环状,即循环队列,如下图:rearfront32107654a8a7a6a5假设为队列开辟的数组单元数目为MAX_QUEUE,在C语言中,它的下标在0MAX_QUEUE-1之间,若增加队头或队尾指针,可以利用取模运算(一个整数数值整除以另一个整数数值的余数)实现。如下所示:fr

17、ont=(front+1)%MAX_QUEUE; rear=(rear+1)%MAX_QUEUE;当front或rear为MAXQUEUE-1时,上述两个公式计算的结果就为0。这样,就使得指针自动由后面转到前面,形成循环的效果。队空和队满的标志问题:队列变为空,队头和队尾指针相等。解决方法:一是为队列另设一个标志,用来区分队列是空还是满;二是当数组只剩下一个单元时就认为队满,此时,队尾指针只差一步追上队头指针,即:(rear+1)%MAX_QUEUE=front。类型定义:#define MAX_QUEUE 10 /队列的最大数据元素数目typedef struct queue /假设当数组只

18、剩下一个单元时认为队满Elemtype elemMAX_QUEUE; /存放队列中数据元素的存储单元int front,rear; /队头指针、队尾指针QUEUE;各项基本操作算法。(1)初始化队列Q void InitQueue(QUEUE *Q)Q-front=-1;Q-rear=-1;(2)入队 void EnQueue(QUEUE *Q,Elemtype elem)if (Q-rear+1)%MAX_QUEUE=Q-front) exit(OVERFLOW);else Q-rear=(Q-reasr+1)%MAX_QUEUE;Q-elemQ-rear=elem; (3)出队 void

19、DeQueue(QUEUE*Q,Elemtype *elem)if (QueueEmpty(*Q) exit(Queue is empty.);else Q-front=(Q-front+1)%MAX_QUEUE;*elem=Q-elemQ-front;(4)获取队头元素内容 void GetFront(QUEUE Q,Elemtype *elem) if (QueueEmpty(Q) exit(Queue is empty.);else *elem=Q.elem(Q.front+1)%MAX_QUEUE;(5)判断队列Q是否为空 int QueueEmpty(Queue Q)if (Q.fr

20、ont=Q.rear) return TRUE;else return FALSE; 3.2.3 队列的链式存储结构及其基本运算的实现在用链式结构存储队列时,需要设置队头指针和队尾指针,以便指示队头结点和队尾结点。结点结构定义如下:typedef struct node /* 队列结点类型定义 */ int data; struct node *next; LinkQueue;typedef struct /* 队列头结点类型定义 */ LinkQueue *front; /* 队列的队首指针 */ LinkQueue *rear; /* 队列的队尾指针 */ Queue;基本运算:(1) 初

21、始化void InitQueue( Queue *Q ) /* 初始化队列,生成一个带哨兵的空队列 */ Q-front = (LinkQueue *)malloc( sizeof(LinkQueue) ); Q-front-next = NULL; Q-rear = Q-front;(2) 判空bool IsEmpty( Queue Q) /* 判断队列是否为空。如果队列为空,返回true,否则返回false */ if( Q.front = Q.rear ) return true; else return false;(3) 进队void EnQueue( Queue *Q, int x

22、) /* 将元素x压入到队列Q中,先申请结点再将其入队 */ Q-rear-next = (LinkQueue *)malloc( sizeof(LinkQueue) ); Q-rear = Q-rear-next; Q-rear-data = x; Q-rear-next = NULL;(4) 出队int DeQueue( Queue *Q ) /* 将队列Q中的队首元素出队 */ LinkQueue *p; int data; if( !IsEmpty( *Q ) ) /* 如果队列非空,则返回队首元素 */ p = Q-front-next; Q-front-next = p-next;

23、 /* 当将队列中的一个元素删除后,指针rear就悬浮起来了, 需要将其调整到正确的状态,即必须使其等于front */ if( p-next = NULL ) Q-rear = Q-front; data = p-data; free( p ); return data; 3.2.4 队列的应用举例例3-9: 汽车加油站。随着城市里汽车数量的急速增长,汽车加油站也渐渐多了起来。通常汽车加油站的结构基本上是:入口和出口为单行道,加油车道可能有若干条。每辆车加油都要经过三段路程,第一段是在入口处排队等候进入加油车道;第二段是在加油车道排队等候加油;第三段是进入出口处排队等候离开。实际上,这三段都

24、是队列结构。若用算法模拟这个过程,就需要设置加油车道数加2个队列。 例3-10:模拟打印机缓冲区。在主机将数据输出到打印机时,会出现主机速度与打印机的打印速度不匹配的问题。这时主机就要停下来等待打印机。显然,这样会降低主机的使用效率。为此人们设想了一种办法:为打印机设置一个打印数据缓冲区,当主机需要打印数据时,先将数据依次写入这个缓冲区,写满后主机转去做其他的事情,而打印机就从缓冲区中按照先进先出的原则依次读取数据并打印,这样做即保证了打印数据的正确性,又提高了主机的使用效率。由此可见,打印机缓冲区实际上就是一个队列结构。例3-11:CPU分时系统在一个带有多个终端的计算机系统中,同时有多个用户需要使用CPU运行各自的应用程序,它们分别通过各自的终端向操作系统提出使用CPU的请求,操作系统通常按照每个请求在时间上的先后顺序,将它们排成一个队列,每次把CPU分配给当前队首的请求用户,即将该用户的应用程序投入运行,当该程序运行完毕或用完规定的时间片后,操作系统再将CPU分配给新的队首请求用户,这样即可以满足每个用户的请求,又可以使CPU正常工作。

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2