栈的基本操作--c语言

•顺序栈

只能从在一端进行插入和删除的线性表是
采用顺序存储的的栈就是顺序栈

typedef struct{
    ElemType data[MaxSize];    //静态数组存放栈中的元素
    int top;    //栈顶指针,指示当前栈顶元素的位置(从0开始的数组下标)
}SqStack;
连续空间)
SqStack S;//声名一个顺序栈(为栈分配一块MaxSize*sizeof(ElemType)大小的连续空间)

 

1.初始化,判空与读取栈顶

//栈的初始化
void InitStack(SqStack &S)
{
    S.top = -1;    //置栈顶指针为-1,栈顶压入元素时从数组下标0开始
}

⋅ \cdot 对栈本身进行操作,所以用引用传递&s,纯c语言用法的话,这里则需要用到指针
⋅ \cdot 结构体访问用s.xxx,如果是结构体指针则是s->xxx

通过判断栈顶指针的值来判断栈空

//栈的判空
bool StackEmpty(SqStack S)
{
    if(S.top == -1){
        return true;
    }
    else{
        return false;
    }
}
//读栈顶元素
bool GetTop(SqStack S, ElemType &x)
{
    if (S.top == -1) {
        return fales;   //栈空
    }

    x = S.data[S.top];    //读栈顶元素
    return true;
}

 

2.进栈和出栈

//进栈
bool Push(SqStack &S, ElemType e)
{
    if (S.top == MaxSize - 1) {
        return false;   //栈满
    }

    S.top++;   //栈顶指针自增1
    S.data[S.top] = e;    //更新栈顶指针指向的栈顶数据为e

    /*
    另一种写法
    S.data[++S.top] = e;
    等价于
    S.top += 1;
    S.data[S.top] = e;
    */

    return true;
}
//出栈,返回值为x
bool Pop(SqStack &S, ElemType &x)
{
    if (S.top == -1) {
        return fales;   //栈空
    }

    x = S.data[S.top];    //栈顶元素出栈
    S.top--;    //更新栈顶指针

    /*
    另一种写法
    S.data[S.top--] = x;
    等价于
    x = S.data[S.top] = x;
    S.top -= 1;
    */

    return true;
}

 

3.共享栈

顺序栈的大小不可变,为了避免内存资源的浪费,提高存储空间的利用率,可以使用共享栈
即两个顺序栈共享一个一维数组空间

typedef struct {
    ElemType data[MaxSize];    //静态数组存放栈中的元素
    int top0;    //0号栈的栈顶指针
    int top1;    //1号栈的栈顶指针
} ShStack;
//共享栈的初始化
S.top0 = -1;
S.top1 = MaxSize;
//共享栈判空
S.top0 == S.top1;

 

4.代码汇总

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MaxSize 10
#define ElemType int

typedef struct {
    ElemType data[MaxSize];    //静态数组存放栈中的元素
    int top;    //栈顶指针,指示当前栈顶元素的位置(从0开始的数组下标)
} SqStack;

typedef struct {
    ElemType data[MaxSize];    //静态数组存放栈中的元素
    int top0;    //0号栈的栈顶指针
    int top1;    //1号栈的栈顶指针
} ShStack;


//----------------------------------------------------------------------------
//栈的初始化
void InitStack(SqStack &S)
{
    S.top = -1;    //置栈顶指针为-1,栈顶压入元素时从数组下标0开始

    /*
    共享栈的初始化
    S.top0 = -1;
    S.top1 = MaxSize;
    共享栈判空
    S.top0 == S.top1;
    */

}

//栈的判空
bool StackEmpty(SqStack S)
{
    if (S.top == -1) {
        return true;
    } else {
        return false;
    }
}
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
//进栈
bool Push(SqStack &S, ElemType e)
{
    if (S.top == MaxSize - 1) {
        return false;   //栈满
    }

    S.top++;   //栈顶指针自增1
    S.data[S.top] = e;    //更新栈顶指针指向的栈顶数据为e

    /*
    另一种写法
    S.data[++S.top] = e;
    等价于
    S.top += 1;
    S.data[S.top] = e;
    */

    return true;
}

//出栈,返回值为x
bool Pop(SqStack &S, ElemType &x)
{
    if (S.top == -1) {
        return false;   //栈空
    }

    x = S.data[S.top];    //栈顶元素出栈
    S.top--;    //更新栈顶指针

    /*
    另一种写法
    S.data[S.top--] = x;
    等价于
    x = S.data[S.top] = x;
    S.top -= 1;
    */

    return true;
}
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
//读栈顶元素
bool GetTop(SqStack S, ElemType &x)
{
    if (S.top == -1) {
        return false;   //栈空
    }

    x = S.data[S.top];    //读栈顶元素
    return true;
}
//----------------------------------------------------------------------------

 
 

•链栈

通常采用单链表实现,所有的操作都在单链表的表头进行
如果链栈不带头结点,则头指针指向的是栈顶元素

而链栈从代码结构上看是可以遍历或者读取元素的,但这影响了栈的后进先出原则。

//不带头结点的链栈
typedef struct LinkNode {
    ElemType data;
    struct LinkNode * next;
} LinkNode, *LiStack;

 

1.初始化,判空和读取栈顶

//链栈的初始化,不带头结点
void InitStack1(LiStack &S)
{
    S = null;   //链栈置空
}

//链栈的判空
bool StackEmpty1(LiStack S)
{
    if (S == null) {
        return ture;
    } else {
        return false;
    }
}
//获取栈顶
bool GetTop1(LiStack S, ElemType &x)
{
    if (S == null) {
        return false;   //栈空
    }

    x = S->data;    //获取栈顶的数据
    return true;
}

 

2.链栈的进栈与出栈

//进栈
bool Pop1(LiStack &S, ElemType e)
{
    LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));

    if (s == null) {
        return false;   //分配新节点不成功
    }

    s->data = e;    //分配入栈结点的数据域
    s->next = S;    //入栈结点的next指向原本的栈顶结点
    S = s;    //更新栈顶结点为s

    return true;
}
bool Push1(LiStack &S, ElemType &x)
{
    if (S == null) {
        return false;   //栈空
    }

    LinkNode* s = S;    //s指向出栈结点
    x = s->data;
    S = S->next;    //更新栈顶结点
    free(s);

    return true;
}

 

3.代码汇总

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MaxSize 10
#define ElemType int
#define bool int

//不带头结点的链栈
typedef struct LinkNode {
    ElemType data;
    struct LinkNode * next;
} LinkNode, *LiStack;


//----------------------------------------------------------------------------
//链栈的初始化
void InitStack1(LiStack &S)
{
    S = null;   //链栈置空
}

//链栈的判空
bool StackEmpty1(LiStack S)
{
    if (S == null) {
        return ture;
    } else {
        return false;
    }
}

//获取栈顶
bool GetTop1(LiStack S, ElemType &x)
{
    if (S == null) {
        return false;   //栈空
    }

    x = S->data;    //获取栈顶的数据
    return true;
}
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
//进栈
bool Pop1(LiStack &S, ElemType e)
{
    LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));

    if (s == null) {
        return false;   //分配新节点不成功
    }

    s->data = e;    //分配入栈结点的数据域
    s->next = S;    //入栈结点的next指向原本的栈顶结点
    S = s;    //更新栈顶结点为s

    return true;
}

//出栈
bool Push1(LiStack &S, ElemType &x)
{
    if (S == null) {
        return false;   //栈空
    }

    LinkNode* s = S;    //s指向出栈结点
    x = s->data;
    S = S->next;    //更新栈顶结点
    free(s);

    return true;
}
//----------------------------------------------------------------------------
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值