栈和队列是两种常见的数据结构,它们分别用于解决不同类型的问题。在程序设计中,栈和队列都是非常重要的数据结构,因为它们可以帮助我们解决很多实际的问题。
栈:
首先,让我们来讨论栈, 栈是一种后进先出( LIFO )的数据结构,它是一种线性的、有序的数据结构。栈的基本操作有两个,即入栈和出栈。入栈指将元素放入栈顶,出栈指将栈顶元素取出。栈的本质是一个容器,它可以存储任何类型的数据,但是栈的大小是固定的,因为它的元素只能在栈顶添加或删除。
栈有许多应用场景,比如我们在浏览网页时,可以使用浏览器的 “返回” 功能,这就是栈的应用之一。当我们浏览网页时,每次点击链接都会将新的页面加入到栈中,而当我们点击 “返回” 按钮时,就会将栈顶的页面弹出,这样就可以回到之前的页面了。另外,栈还可以用于括号匹配、表达式求值等问题的解决。
队列:
接下来,我们来介绍队列。队列是一种先进先出( FIFO )的数据结构,它与栈相似,也是一种线性的、有序的数据结构。队列的基本操作有三个,即入队、出队和查看队首元素。入队指将元素放入队尾,出队指将队首元素取出。队列的本质也是一个容器,它可以存储任何类型的数据,但是队列的大小也是固定的。
队列也有很多应用场景,比如操作系统中的进程调度。操作系统中有很多进程需要运行,操作系统通过队列来管理这些进程。当一个进程需要运行时,就将它加入到队列的队尾,当操作系统分配到一个 CPU 时,就将队首的进程取出来运行,这样就可以保证每个进程都能得到运行的机会。
除了以上应用场景外,栈和队列还有很多其他的应用,比如栈还可以用于实现递归算法,队列用于广度优先搜索等。下面就让我们通过几个经典问题深入了解栈和队列吧!
栈、队列与一般线性表的区别
栈、队列是一种特殊(操作受限)的线性表
区别:仅在于运算规则不同
顺序栈的表示和实现
存储方式:同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元
依次存放自栈底到栈顶的数据元素。栈底一般在低地址端。
-
附设top指针,指示栈顶元在顺序栈中的位置。
-
另设base指针,指示栈底元素在顺序栈中的位置。
-
用stacksize表示栈可使用的最大容量
但是,为了方便操作,通常top指示真正的栈顶元素之上的下标地址
顺序栈的表示
top 指示真正的栈顶元素之上的下标地址
栈满时的处理方法:
-
报错,返回操作系统。
-
分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈。
使用数组作为顺序栈存储方式的特点:简单方便、但易产生溢出(数组大小固定)
-
上溢(overflow):栈已经满,又要压入元素
-
下溢(underflow):栈已经空,还要弹出元素
#define MAXSIZE 100
typedef struct
{ SElemType *base; SElemType *top;
int stacksize;
}SqStack;
链栈的表示和实现
运算是受限的单链表,只能在链表头部进行操作,故没有必要附加头结点。
栈顶指针就是链表的头指针
注意:链栈指针的方向
typedef struct StackNode {
SElemType data;
struct StackNode *next;
} StackNode, *LinkStack;
LinkStack S;