栈---链栈

一、栈的链式存储结构

栈的链式存储结构,简称为链栈。链栈是没有附加头结点的运算受限的单链表。栈顶指针就是链表的头指针。

栈是用栈顶来做插入和删除操作,那么对于链栈的栈顶放在链表的头部还是尾部呢?

单链表有头指针,而栈顶指针也是必须的,所以比较好的办法是把栈顶放在单链表的头部。另外,都已经有了栈顶在头部了,单链表中比较常用的头结点也就失去了意义,通常对于链栈来说,是不需要头结点的。

链栈的结构如下:
这里写图片描述

对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是 top=NULL 的时候。

二、实现要点

1、初始化。初始化的目标是要构造一个空栈。空栈的特性:
(1)栈的count = 0
(2)栈的 top 为 null

LinkStack *InitStack(LinkStack *s)
{
    s->top = (StackNode*)malloc(sizeof(StackNode));
    //空栈的特性(1)(2)
    s->top = NULL;//(1)
    s->count = 0;//(2)
    return s;
}

2、进栈。假设为要插入的元素e开辟的新节点为p,那么插入过程为:首先开辟一个内存空间给 p,然后 p的data就是e,再将新结点sp的后继赋值为当前结点 s->top。最后将栈顶指针指向结点 p。
这里写图片描述

总结为两步:

(1)处理新结点p的后继,这个后继就是原本的栈顶结点。
(2)将栈顶指针 top 重新指向新结点p

代码:

LinkStack *Push(LinkStack *s, SElemType e)
{
    StackNode *p= (StackNode*)malloc(sizeof(StackNode));//要插入的节点
    p->data = e;
    //实现入栈
    p->next = s->top;//(1)新节点后继为原栈顶节点
    s->top = p;//(2)将新的结点p赋值给栈顶指针

    s->count++;
    return s;
}

3、出栈。大致过程为:假设变量p用来存储要删除 的栈顶结点,将栈顶指针下移一位,最后释放p即可。
这里写图片描述

代码:

LinkStack *Pop(LinkStack *s)
{
    if(s->top == NULL)//栈空的判断!!!
    {
        cout<<"栈已空,无法执行弹出操作!"<<endl;
    }
    else
    {
        StackNode *p= (StackNode*)malloc(sizeof(StackNode));//(1)要弹出的节点
        p = s->top;//(2)栈顶节点赋给p
        cout<<p->data<<"出栈"<<endl;
        s->top = p->next;//(3)栈顶指针下移一位,指向后一结点
        free(p);//(4)释放p
        s->count--;
    }
    return s;
}

4、置空链栈。方法是设置两个工作结点,开始循环。在释放p之前,让q成为p的后继。还是那个比喻,在皇帝死之前,册封皇子。free(p); 皇帝死了,p=q; 皇子就成了新皇帝。(类似单链表的置空操作)。
代码:

LinkStack *ClearStack(LinkStack *s)
{
    StackNode *p, *q;
    p = s->top;
    while(p)
    {
        q = p->next;//(1)让q成为p的后继
        free(p);//(2)释放p
        p = q;//(3)q赋给p
    }
    s->top=NULL;//(4)!!!
    s->count = 0;
    return s;
}

链栈实现代码:

#include<iostream>
#include<stdlib.h>
using namespace std;

typedef int SElemType;

//节点类型
typedef struct StackNode
{
    SElemType data;
    struct StackNode *next;
}StackNode;

typedef struct
{
    StackNode *top;//栈顶指针
    int count;//记录栈中元素个数
}LinkStack;
//初始化
LinkStack *InitStack(LinkStack *s)
{
    s->top = (StackNode*)malloc(sizeof(StackNode));
    //空栈的特性(1)(2)
    s->top = NULL;//(1)
    s->count = 0;//(2)

    return s;
}
//入栈
LinkStack *Push(LinkStack *s, SElemType e)
{
    StackNode *p= (StackNode*)malloc(sizeof(StackNode));//要插入的节点
    p->data = e;
    //实现入栈
    p->next = s->top;//(1)新节点后继为原栈顶节点
    s->top = p;//(2)将新的结点p赋值给栈顶指针

    s->count++;
    return s;
}
//出栈
LinkStack *Pop(LinkStack *s)
{
    if(s->top == NULL)//栈空的判断!!!
    {//count为0也可说明栈为空
        cout<<"栈已空,无法执行弹出操作!"<<endl;
    }
    else
    {
        StackNode *p= (StackNode*)malloc(sizeof(StackNode));//(1)要弹出的节点
        p = s->top;//(2)栈顶节点赋给p
        cout<<p->data<<"出栈"<<endl;
        s->top = p->next;//(3)栈顶指针下移一位,指向后一结点
        free(p);//(4)释放p
        s->count--;
    }
    return s;
}
//置空链栈
LinkStack *ClearStack(LinkStack *s)
{
    StackNode *p, *q;
    p = s->top;
    while(p)
    {
        q = p->next;//让q成为p的后继
        free(p);//释放p
        p = q;//q赋给p
    }
    s->top=NULL;//!!!
    s->count = 0;
    return s;
}
//打印
void PrintStack(LinkStack *s)
{
    StackNode *p;
    p = s->top;
    while(p)//top为空时链栈为空
    {
        cout<<p->data<<" ";
        p = p->next;
    }
    cout<<endl;
}
int main()
{
    LinkStack *s = InitStack(s);
    cout<<"************************"<<endl;
    Push(s, 1);
    PrintStack(s);
    Push(s, 2);
    PrintStack(s);
    Push(s, 3);
    PrintStack(s);
    Push(s, 4);
    PrintStack(s);//后入先出,逆序打印
    cout<<"************************"<<endl;
    Pop(s);
    PrintStack(s);
    Pop(s);
    PrintStack(s);
    Pop(s);
    PrintStack(s);
    Pop(s);
    PrintStack(s);
    cout<<"************************"<<endl;
    Pop(s);
    cout<<"************************"<<endl;
    Push(s, 1);
    PrintStack(s);
    cout<<"************************"<<endl;
    ClearStack(s);
    PrintStack(s);
    cout<<"************************"<<endl;
    return 0;
}

结果:

************************
1
2 1
3 2 1
4 3 2 1
************************
4出栈
3 2 1
3出栈
2 1
2出栈
1
1出栈

************************
栈已空,无法执行弹出操作!
************************
1
************************

************************

Process returned 0 (0x0)   execution time : 1.625 s
Press any key to continue.
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值