数据结构基础之栈与递归

来源:互联网 发布:北京美工培训班学费 编辑:程序博客网 时间:2024/04/27 04:21


1栈的定义。栈(stack)是限定仅在表尾进行插入和删除操作的线性表,一般把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表,简称为LIFO结构。栈的插入操作叫做进栈,删除叫出栈。栈也是按照顺序存储结构存储数据的,用下标为0的一端为栈底,当栈存在一个元素时,top等于0,因此通常把空栈的判定为top等于-1。
2 两栈共享空间。最大限度的利用存储空间,数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为数组的末端,即下标为数组长度n-1处。这样,如果两个栈增加元素,就是两端点向中间延伸。他们是从数组的两端向中间靠拢,直到他们见面为止。通常是在当两个栈的空间需求有相反关系时才使用这样的数据结构,否则两个栈都在不停的增长,那很快就会因栈满而溢出。而且这也只是针对两个具有相同数据类型的栈,否则会使得问题更加麻烦。
3 栈的链式存储结构。单链表有头指针,而栈顶指针也是必须的,所以一般把栈顶放在单链表的头部,让其“合二为一”。栈顶已经在头部了,单链表中常用的头节点也就失去了存在的必要,通常链栈不需要头结点。对于链栈来说基本不存在栈满的情况,除非内存已经没有可以使用的空间。对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top==NULL的时候。
4 顺序栈与链栈的对比。它们在时间复杂度上都是O(1)。对于空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费或不足的问题,但是他的优势在于随机存取快速,而链栈需要每个元素包含指针域,这就增加了内存消耗,当是可以灵活的存储数据。一般来说,如果栈在使用过程中无法预料那么使用链栈,如果它的变化在可控范围内,使用顺序栈。
5 栈的作用。栈的引入简化了程序设计的问题,划分了不同关注层次,使得思考范围缩小,更加聚焦于我们要解决的问题核心。反之,像数组等,需要分散精力去考虑数组的下标增减等细节问题,反而掩盖了问题的本质。
6 栈的应用-递归。在高级语言中,调用自己和其他函数并没有本质的不同。我们把一个直接调用自己或通过一系列的调用语句间接调用自己的函数,称为递归函数。每个递归定义必须至少有一个条件,满足时递归不再进行,即不再引用自身而是返回值退出。迭代使用的是循环结构,递归使用的是选择结构。递归能使程序的结构更清晰、简洁,但是会建立函数的副本耗费更多的时间和内存。
递归分为前行和退回阶段。递归过程退回的顺序是它前行顺序的逆序。在退回过程中,可以执行一些动作,如恢复在前行过程中存储起来的某些数据。这种存储某些数据并在后面又以存储的逆序恢复这些数据的行为,很符合栈这样的数据结构,因此,编译器就使用栈实现递归。
在递归的前行阶段,对于每一层递归,函数的局部变量、参数值以及返回地址都被压入栈中。在退回阶段,位于栈顶的局部变量、参数值和返回地址被弹出,用于返回调用层次中执行代码的其余部分,也就是恢复了调用的状态

0 0
原创粉丝点击