一、引言
栈和队列也是线性表,但是不同的是他们的基本操作是线性表操作的子集
二、栈和队列的定义和特点
2.1、栈的定义
栈-特点:后进先出
栈是一种先进后出的线性表,栈的插入和删除操作都只能在栈顶进行,而一般的线性表 可以在线性表的任何位置进行插入和删除操作。
队列-特点:先进先出
队列是一种先进先出的线性表,队列的插入只能在队尾进行,队列的删除只能在队头进行, 而一般的线性表可以在线性表的任何位置进行插入和删除操作
2.2、栈的数学性质
n个不同的元素进栈,出栈元素不同排列的个数为:如下图(成为卡特兰数)
例如:有五个元素abcde,进栈顺序为abcde,那么合法的出栈顺序为?
三、栈的存储结构
栈类似于线性表,也有两种存储方法:顺序存储、链式存储
3.1、栈的顺序存储结构
3.1.1顺序栈
两个状态:
- 栈空状态:
S.top==-1
或者S.top==0
,根据不同的规定条件判定栈空状态
当S.top==0时,会浪费一个元素空间大小 - 栈满状态:
S.top==MaxSize-1
三个操作:
Push进栈
Pop出栈
Top读取栈顶元素
-
元素进栈操作:栈不满的时候,栈顶指针先加1,再将值到栈顶元素
S.date[++S.top]=x;//指针+1,在入栈
相当于:
++(S.top);
S.data[S.top] = x;
相当于:
x = S.data[S.top];
--(S.top);
- 元素出栈操作:
x=S.data[S.top--];//元素先出栈,指针再减1
3.1.2共享栈
目的:共享栈是为了更有效的利用存储空间,两个栈的空间相互调节,只有在整个存储空间被占满时才能发生上溢
3.2、栈的链式存储
链栈用单链表实现,一般尾节点为栈底,使用头指针指向的节点作为栈顶,不需要头节点。
两个状态:
- 栈空状态:
lst->next == NULL
- 栈满状态:可以说不存在栈满状态
两个操作:
进栈/出栈都只能在栈顶 一端进行(链头作为栈顶)
四、基本操作
基本运算/操作:是指的该结构最核心、最基本的运算,其他较复杂的操作可以通过基本操作实现
关于栈、队列、链表、树等一系列结构都有的一些基本运算/操作:
- 判断是否为空
- 有多少个元素/结点
- 清空结构体
- 对可访问的边界节点的删除/插入/返回操作(队列特殊)
五、注意
栈空有两种状态:S.top==-1
或者S.top==0
S.top==-1
指的是:空栈时,将top指针设置为-1,
0是第一个元素,如果用top=0就表示有一个元素,则栈就不为空。
-
当有数据进栈时,现将指针top指针+1,再将数据存入top指针
S.top=S.top+1;
S.data[S.top] =x;
等价于:S.data[++S.top] = x; -
当有数据出栈时,先将数据从top指针中删除,在将top-1
x = S.data[S.top];
S.top == S.top-1;
等价于:x=S.data[S.top–];
注意:
若先指针下移会导致程序代码错误,是错误的写法
S.top==0
指的是:空栈时,将top指针设置为0
(在链栈中这种情况其实相当于指针指向的是头结点!)
- 当有数据进栈时,先将数据放入top指针,再将top指针往后移
S.data[S.top] = x;
S.top= S.top+1;
- 等价于:S.data[S.top++] =x;
- 当有数据出栈时,先将top指针-1,再将数据取出
S.top=S.top-1;
x = S.data[S.top];
- 等价于:x = S.data[–top]