您的位置:首页 > 理论基础 > 数据结构算法

数据结构(二)—栈

2020-04-07 13:24 211 查看

目录
  • 数据结构(二)—栈 一、栈的概念及特点 概念
  • 特点
  • 基本操作
  • 分类
  • 二、顺序栈实现
      存储结构
    • 初始化
    • 入栈
    • 出栈
    • 取栈顶元素
    • 验证
  • 三、链栈实现
      存储结构
    • 初始化
    • 入栈
    • 出栈
    • 取栈顶元素
    • 验证
  • 四、总结
  • 数据结构(二)—栈

    一、栈的概念及特点

    概念

    (stack)是限定仅在表尾进行插入或删除操作的线性表,其表尾端称为栈顶(top),表头端称为栈底(bottom),不含元素的空表称为空栈。

    特点

    后进先出(LIFO,Last In First Out)

    基本操作

    • 初始化
    • 入栈
    • 出栈
    • 取栈顶元素

    分类

    根据存储结构不同,我们又可以把栈分为顺序栈链栈

    下面我们分别来实现这两种存储结构的栈。

    二、顺序栈实现

    顺序栈一般是用数组来实现,存在两个指针,栈顶、栈底指针,分别指向数组的尾部和头部,如下图:

    栈空的条件即是top==base。比较好理解,下面直接上代码:

    存储结构

    //栈-顺序栈实现
    #include<iostream>
    using namespace std;
    
    int const N=100;
    //顺序栈的存储结构
    typedef int SElemType;
    typedef struct
    {
    SElemType *base;//栈底指针
    SElemType *top;//栈顶指针
    int stackSize;//栈可用的最大容量
    }SqStack;

    初始化

    //栈初始化
    void InitStack(SqStack &s)
    {
    s.base=new int
    ;//为顺序栈动态分配一个最大容量为N的数组空间
    s.top=s.base;//top初始为base,表示空栈
    s.stackSize=N;//stacksize置为栈的最大容量N
    }

    入栈

    //入栈,插入元素data为新的栈顶元素
    void Push(SqStack &s, SElemType data)
    {
    if(s.top-s.base==s.stackSize)
    {//栈满
    cout<<"栈已满!"<<endl;
    return;
    }
    *s.top=data;//将元素data入栈
    *s.top++;//栈顶指针加1
    }

    出栈

    //出栈,删除栈顶元素,用data返回其值
    void Pop(SqStack &s,SElemType &data)
    {
    if(s.base==s.top)
    {
    cout<<"栈为空!"<<endl;
    return;
    }
    data=*s.top;
    *s.top--;//栈顶指针减1
    }

    取栈顶元素

    //返回s的栈顶元素,不修改栈顶指针
    int GetTop(SqStack &s)
    {
    if(s.base!=s.top)//栈非空
    return *(s.top-1);
    }

    验证

    int main()
    {
    SqStack myStack;
    InitStack(myStack);
    Push(myStack,1);
    Push(myStack,2);
    Push(myStack,3);//将1,2,3依次入栈
    cout<<"栈顶元素:"<<GetTop(myStack)<<endl;//获取当前栈顶元素
    int a;
    Pop(myStack,a);//出栈
    cout<<"弹出栈顶元素后,现栈顶元素为"<<GetTop(myStack)<<endl;//获取当前栈顶元素
    return 0;
    }

    运行以上代码后,运行结果如下:

    三、链栈实现

    链栈一般采用单链来表示:

    存储结构

    //链栈实现
    #include<iostream>
    using namespace std;
    
    //链栈的存储结构
    typedef char ElemType;
    typedef struct StackNode
    {
    ElemType Data;//数据域
    StackNode *Next;//指针域
    }StackNode,*LinkStack;

    初始化

    //初始化,构造一个空栈S,栈顶指针置空
    void InitStack(LinkStack &S)
    {
    S=NULL;
    }

    入栈

    与顺序站不同的是,链栈在入栈前不需要判断栈是否满,只需要为入栈元素动态分配一个结点空间,如下图:

    //入栈,在栈顶插入元素data
    void Push(LinkStack &S,ElemType data)
    {
    StackNode *p=new StackNode();//生成新结点
    p->Data=data;//将新节点数据域置为data
    p->Next=S;//将新节点插入栈顶
    S=p;//修改栈顶指针为p
    }

    出栈

    和顺序栈一样,出栈是需要判断栈是否为空,不同的是,链栈在出栈后需要释放出栈元素的栈顶空间,如下图:

    //出栈,删除S的栈顶元素,并用data返回其值
    void Pop(LinkStack &S,ElemType &data)
    {
    if(S==NULL)
    {//栈为空
    cout<<"栈为空!"<<endl;
    return;
    }
    data=S->Data;//将栈顶元素赋给data
    StackNode *p=S;//用p临时保存栈顶元素空间,以备释放
    S=S->Next;//修改栈顶元素
    delete p;//释放原栈顶元素的空间
    }

    取栈顶元素

    //返回S栈顶元素,不修改栈顶指针
    ElemType GetTop(LinkStack &S)
    {
    if(S!=NULL)//栈非空
    return S->Data;
    }

    验证

    //打印栈
    void PrintStack(LinkStack &S)
    {
    if(S!=NULL)
    {
    StackNode *p=S;
    while(p!=NULL)
    {
    cout<<p->Data<<"\t";
    p=p->Next;
    }
    cout<<"\n";
    }
    }
    
    int main()
    {
    LinkStack LS;
    InitStack(LS);//初始化栈
    Push(LS,'a');
    Push(LS,'b');
    Push(LS,'C');//将a b C依次入栈
    PrintStack(LS);//打印当前栈
    ElemType a;
    Pop(LS,a);//将C出栈
    PrintStack(LS);//打印当前栈
    cout<<"栈顶元素为:"<<GetTop(LS);//当前栈顶元素元素
    return 0;
    }

    运行结果如下:

    四、总结

    栈的实现相对来说比较简单,主要掌握顺序栈和链栈的实现即可~

    参考资料:《数据结构(C语言)(第2版)》 严蔚敏等著

    写文不易~因此做以下申明:

    1.博客中标注原创的文章,版权归原作者 煦阳(本博博主) 所有;

    2.未经原作者允许不得转载本文内容,否则将视为侵权;

    3.转载或者引用本文内容请注明来源及原作者;

    4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签:  c++ amp next