从0开始学习数据结构-堆栈的顺序存储结构

445 阅读3分钟

这是我参与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. 前提是堆栈不空
  2. 堆栈不空时返回1,否则返回0
  3. 该操作不会改变栈顶指针的位置
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), 这些操作与堆栈的长度无关。