这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战
顺序堆栈的构造
堆栈的顺序结构可以利用一个具有M个元素的数组STACK[0, ..., M-1]来描述。
里面相关的概念如下:
- STACK:堆栈的名字
- M:数组的上界,表示堆栈的最大容量
- top:一个整型变量,表示栈顶指针,指出某一时刻堆栈栈顶元素的位置
- 堆栈不空时:top的值就是数组某一元素的下标值 STACK[top]表示当前的栈顶元素
- 堆栈为空栈时:top = -1
- 溢出问题:堆栈是动态结构,数组是静态结构,,利用一个静态结构的数组描述一个动态结构的堆栈,存在着溢出(overflow)问题
- 上溢:堆栈中已经有M个元素时,如果在进栈操作产生的溢出
- 下溢:对空栈进行删除操作时产生的溢出
为了避免溢出,对堆栈进行进栈和退栈的操作之前,需要判断堆栈是否已满或者是否为空
堆栈的顺序存储结构的类型描述: ※
#defile M 1000 // 定义堆栈的最大容量
SElemType STACK[M];
int top; // 栈顶指针变量
顺序堆栈的基本算法
顺序存储结构下,堆栈常用的几种操作的算法有:
- 初始化一个堆栈
void INITIALS(int &top) // ※
{
top = -1;
}
- 判断堆栈是否为空
int EMPTYS(int top) // ※
{
return top == -1; // 堆栈为空时返回1,否则返回0
}
- 判断堆栈是否已满
int FULLS(int top) // ※
{
return top = M-1; // 堆栈已满时返回1,否则返回0
}
- 取当前栈顶元素
※定义变量item,存储获取到的栈顶元素。 思路:
- 前提是堆栈不空
- 堆栈不空时返回1,否则返回0
该操作不会改变栈顶指针的位置
int GETTOPS(SElemType STACK[], int top, SElemType &item) {
/* top为栈顶指针变量 */
if (EMPTYS(top))
return 0; // 堆栈为空时操作失败,返回0
else {
item = STACK[top]; // 保存栈顶元素
return 1; // 堆栈非空,操作成功,返回1
}
}
- 进栈
※在容量为M的堆栈中插入一个新的数据元素item,栈顶元素的位置由top指出。 思路:- 判断上溢条件,若产生溢出,返回0,插入失败,算法结束.
栈顶指针top向前移动一个位置,将item插入到修改以后的top指针指向的位置,返回1,插入成功.
算法:
int PUSH(SElemType STACK[], int &top, SELemType item)
{
// top为栈顶指针
if(FULLS(top))
return 0; // 堆栈已满,插入失败,返回0
else {
STACK[++top] = item;
return 1; // 堆栈未满,插入成功,返回1
}
}
- 退栈
※定义变量item,从堆栈中退出当前的栈顶元素,并保存在item中,同事修改栈顶指针的位置。
思路:
- 首先判断堆栈是否为空,若为空栈,返回0,表示删除失败,算法结束
- 若需要保存栈顶元素,则保留在item中
将栈顶指针后退一个位置,返回1,表示删除成功
注意:这里所谓的删除,只是将栈顶指针“后退”一个位置,原来的栈顶位置中存的元素依然存在,只是被认为不作为当前栈中的元素而已(实际上该元素还占据原来的位置,当有新的数据元素进栈时就会将其“冲掉”)。
算法:
int POP(SElemType STACK[], int &top, SElemType &item)
{
// top为栈顶指针变量
if(EMPTYS(top))
return 0; // 堆栈为空,删除失败,返回0
else {
item = STACK[top--]; // 保存栈顶元素
return 1; // 堆栈非空,删除成功,返回1
}
}
无论进栈还是退栈,关键的一步都是修改栈顶指针top的位置。
上面几种算法的时间复杂度均为O(1), 这些操作与堆栈的长度无关。