栈的基本结构与基本操作

  栈也是一种特殊的线性表,但不同的是,栈的操作与传统的线性表不同。传统的线性表可以完成随机位置存取,而栈的结构决定了它进行操作的特点:仅仅在表尾进行插入或删除操作(后进先出)。表尾端称作栈顶,而与之相对的,表头端称作栈底。可以将栈的结构与子弹弹夹进行类比,后压入的子弹先被发射,正如栈的后进先出特点一般。

    假设栈中的元素如下所示:a_{1},a_{2},a_{3}....a_{n},若设置a_{1}作为栈底元素,与之相对的a_{n}则作为栈顶的元素,a_{n}是最后一个被压入栈的,同时也会是第一个出栈的。元素输入栈的顺序与输出栈的顺序直接相反。栈的结构示意图如下:

栈的结构

   栈的顺序表示基本结构如下,要求利用一组地址连续的内存单元来存储信息,元素的数据按顺序由栈底依次存储到栈顶,再由栈顶开始依次向下取出或添加元素 。在栈的顺序表示之中,先定义栈的类名为SqStack,需要设置名为base与top的两个指针,分别指示栈底的内存与栈顶的内存,同时定义int类型的变量用于设置栈的内存。代码如下:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define size 1000
#define incresize 10
using namespace std;
typedef struct 
{
    int *base;
    int *top;
    int stacksize;
}SqStack;

    在定义了栈的基本结构后,按照设定的分配量size分配结点指针所指的内存的空间,base名为栈底指针,指向栈底部元素的内存。top名为栈顶指针,初始化与base指针指向相同,栈的内存设置为size变量。插入与删除元素之时,仅仅需要移动栈顶指针即可。由栈的指针的结构可以看出,非空栈的栈顶指针始终指向的是栈顶元素的上一个位置,这与顺序表插入节点的操作也是类似的。顺序栈的结构初始化代码如下:

void Init(SqStack s)
{
    s.base=(int *)malloc(size*sizeof(int));
    s.top=s.base;
    s.stacksize=size;
}

   栈进行了初始化操作后,开始定义三个基本操作,分别是入栈出栈以及获取栈顶元素。入栈操作主要思路如下:1)先进行内存是否溢出的判别,由于栈所占用的内存是连续一片内存,所以,当栈顶指针减去栈底指针的数值差大于栈的设置长度时,需要重新定义栈底指针(base)所指的内存的大小    2)进行判别完毕后,重置top指针指向的内存    3)将元素e入栈,具体操作为栈顶指针top上移一位,指针所指的内存赋值为e(返回值为e)。具体代码如下:

void push(SqStack s,int e)
{
    if(s.top-s.base>s.stacksize)
    {
        s.base=(int*)realloc(s.base,(s.stacksize+incresize)*sizeof(int));
        s.top=s.base+s.stacksize;
        s.stacksize+=incresize;
    }
    *s.top++=e;
}

  与入栈操作相反地,出栈操作不需要进行内存的判别,只需要先将栈顶指针下移,接着用int类型的变量e返回栈顶元素的值即可。具体代码如下:

void pop(SqStack s,int e)
{
    if(s.top!=s.base)
    {
        e=*(--s.top);
    }
    cout<<e<<endl;
}

根据栈的结构,不难得出获得栈顶元素的具体操作 :仅仅只需要访问栈顶指针所指内存的下一个单位内存,并用int 类型的变量e返回该指针所指内存的数据域。   具体代码如下:

void GetTop(SqStack s,int e)
{
    if(s.top!=s.base)
    {
        e=*(s.top-1);
        cout<<e<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_38846633/article/details/81328284