C语言栈基本操作

c语言里栈的类型包括顺序栈和链表栈。

1. 顺序栈

 顺序栈中的栈底指针base不会改变指向,改变的是top指针的指向。代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
// 顺序栈

#define MAXSIZE 100

typedef struct stack
{
    int *base;     // 栈底指针
    int *top;      // 栈顶指针
    int index;     // 用int值记录栈顶位置
    int stacksize; // 容量
} SqStack;

void InitStack(SqStack *S)
{
    S->base = (int *)malloc(MAXSIZE * sizeof(int));
    // S->top = (int *)malloc(MAXSIZE * sizeof(int));
    S->top = S->base; // 栈顶指向base栈底,表示栈为空
    S->index = 0;     // 也可用一个int数值判断栈是否为空,0为空
    S->stacksize = MAXSIZE;
}

void Push(struct stack *S, int data)
{
    if (S->top - S->base == S->stacksize)
    {
        puts("顺序栈已满");
        return;
    }
    S->top++;         // 栈顶指针首地址指向当前地址的下一个地址
    *(S->top) = data; // 第一次执行时,访问s.top等价于s.base + 1
}

void Pop(struct stack *S, int *data)
{
    if (S->base == S->top)
    {
        // 栈顶指向栈底
        *data = -1;
    }
    *data = *(S->top);
    S->top--; // 栈顶指向上一个地址
}

int getTop(struct stack *S)
{
    return *(S->top);
}

void clearStack(struct stack *S)
{
    S->base = NULL;
    S->top = NULL;
    S->index = 0;
    S->stacksize = MAXSIZE;
}

char *StackEmpty(struct stack *S)
{
    if (S->base == S->top)
    {
        return "yes"; // 是空栈
    }
    else
        return "no";
}

int StackLength(struct stack *S)
{
    return S->top - S->base;
}

void printStack(struct stack *S)
{
    int length = StackLength(S);
    int i = 1;
    while (i <= length)
    {
        printf("顺序栈的第%d个元素:%d\n", i, *(S->base + i));
        i++;
    }
}

int main()
{
    SqStack node;
    InitStack(&node);
    Push(&node, 11);
    Push(&node, 12);
    Push(&node, 13);
    Push(&node, 14);
    puts("---打印添加后的顺序栈里的元素---");
    printStack(&node);
    printf("顺序栈的长度:%d\n", StackLength(&node));
    puts("---删除顺序栈里的元素---");
    int removeData = -1;
    Pop(&node, &removeData);
    printf("第一次删除的数据:%d\n", removeData);
    Pop(&node, &removeData);
    printf("第二次删除的数据:%d\n", removeData);
    puts("---打印删除后的顺序栈里的元素---");
    printStack(&node);
    clearStack(&node);
    printf("顺序栈是否为空:%s\n", StackEmpty(&node));
    return 0;
}

2. 链表栈

  

 链表栈和单链表的定义一致,使用头插法操作栈顶指针。栈顶始终代表头结点,入栈就将新的节点作为头结点,出栈就将栈顶指向头结点的下一个节点来删除头结点:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
// 链表栈头节点始终指向栈顶

#define MAXSIZE 100

typedef struct StackNode
{
    int data;
    struct StackNode *next;
} StackNode, *LinkStack;

void InitLinkStack(LinkStack *S)
{
    *S = NULL;
}

void Push(LinkStack *S, int data)
{
    struct StackNode *p = (struct StackNode *)malloc(sizeof(struct StackNode));
    p->data = data;
    printf("数据%d入栈\n", data);
    p->next = *S;
    *S = p;
}

int getTop(LinkStack *S)
{
    return (*S)->data;
}

void printStack(LinkStack *S)
{
    struct StackNode *p = *S;
    puts("---从栈顶开始输出内容---");
    while (p)
    {
        printf("%d\n", p->data);
        p = p->next;
    }
    delete p;
}

void Pop(LinkStack *S, int *popData)
{
    // struct LinkStack *p = *S;
    if(*S == NULL) {
        *popData = -1;
    } else {
        *popData = (*S)->data;
        *S = (*S)->next;
        puts("栈顶数据被删除");
    }
}

int main()
{
    LinkStack stack;
    InitLinkStack(&stack);
    Push(&stack, 11);
    Push(&stack, 12);
    Push(&stack, 13);
    int top = getTop(&stack);
    printf("栈顶元素:%d\n", top);
    printStack(&stack);

    int data = -1;
    Pop(&stack, &data);
    printf("删除的数据:%d\n", data);
    printStack(&stack);

    Push(&stack, 14);
    printStack(&stack);

    return 0;
}

应用场景有表达式求值:

注意当OPTR栈顶元素大于当前字符ch时,会进行计算并且不会读入下一字符,这里其实是多个循环:只要栈顶的运算符优先级较高,那么就一直把这个运算符进行计算,例如1+2*3+5:

当读取到第二个+时,此时OPTR里是[+,*],栈顶是*。OPND里是[1,2,3],栈顶是*。比较第二个+号和*,乘法的优先级更高,这时候OPTR出栈乘法符号*,OPND出栈两个数2和3,计算得6并入栈。此时OPTR里还有[+],OPND里还有[1,6]。由于两个+号之间前面的优先级高,所以OPTR栈顶的+优先级更高,此时继续取出+号和两个数1和6进行运算得到7。此时OPTR为空栈,OPND为[7]。然后第二个+就可以入栈并读取下一个字符5了。下一次计算的就是7+5,这也符号数学里的运算逻辑。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heine162

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值