栈的基本操作及其应用


一、栈的基本概念

栈(stack)是限定仅在表尾进行插入和删除操作的线性表

我们把允许插入和删除的一端成为栈顶,另一端为栈底,不含任何数据元素的栈称为空栈。特点是“先进后出(LIFO结构)”

在这里插入图片描述
在这里插入图片描述

二、栈的基本操作

1.创建一个栈

代码如下(示例):

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

#define StackInitSize 10 // 初始化栈的最大长度
#define StackIncrement 10 // 若栈最大空间不够时,需要增加的长度
typedef int ElemType;
typedef int Status;

typedef struct {
    ElemType* base; // 栈底指针
    ElemType* top; // 栈顶指针
    int stacksize; // 栈的最大长度
} SqStack;

2.初始化栈

代码如下(示例):

//构造一个空栈S
Status InitStack(SqStack &S) {
    // 分配初始空间
    S->base = (ElemType*)malloc(StackInitSize * sizeof(ElemType));
    if (!S->base) {
        exit(0);
    }
    S->top = S->base; /// 栈顶与栈底相同
    S->stacksize = StackInitSize; // 栈的最大长度等于初始长度
    return 1;
}

3.销毁栈

代码如下(示例):

// 栈顶栈底指针置为NULL,长度置为0
Status DestroyStack(SqStack* S) {
    free(S->base);
    S->base = S->top = NULL;
    S->stacksize = 0;
    return 1;
}

4.判定S是否为空

Status StackEmpty(SqStack* S) {
    return S->base == S->top;//判断栈顶指针与栈底指针是否相同
}

5.求栈的长度

Status StackLength(SqStack* S) {
    if (S->top == S->base) {
        return 0;
    }
    return (Status)(S->top - S->base);//栈顶减去栈底指针即为栈的长度
}

6.取栈顶元素

Status GetTop(SqStack* S, int &e) {
    if (S->top == S->base) {
        return 0;
    }
    e = *(S->top - 1);
    return e;
}

7.遍历打印栈

Status TraverseStack(SqStack* S) {
    ElemType* p;

    if (S->top == S->base) {
        printf("Stack is NULL.\n");
        return 0;
    }
    p = S->top;
    while (p > S->base) {
        p--;
        printf("%d ", *p);
    }
    printf("\n");
    return 1;
}

8.入栈操作

Status Push(SqStack* S, int &e) {
    // 若栈的最大长度不会够用时,重新开辟,增大长度
    if (S->top - S->base >= S->stacksize) {
        S->base = (ElemType*)realloc(S->base, (S->stacksize + StackIncrement) * sizeof(ElemType));
        if (!S->base) {
            return 0;
        }
        // 栈顶指针为栈底指针加上栈之前的最大长度
        S->top = S->base + S->stacksize;
        // 栈当前的最大长度等于栈之前的最大长度与增加的长度之和
        S->stacksize += StackIncrement;
    }
    *S->top++ = e; // 先赋值,后栈顶指针上移
    return e;
}

9.出栈操作

 Status Pop(SqStack* S, int &e) {
   if (S->base == S->top) {
       return 0;
   }
   e = *--S->top;  // 栈顶指针先下移,后赋值
   return e;
}

三,完整代码

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

#define StackInitSize 10 // 初始化栈的最大长度
#define StackIncrement 10 // 若栈最大空间不够时,需要增加的长度
typedef int ElemType;
typedef int Status;

typedef struct {
    ElemType* base; // 栈底指针
    ElemType* top; // 栈顶指针
    int stacksize; // 栈的最大长度
} SqStack;

// 初始化栈
Status InitStack(SqStack *S) {
    // 分配初始空间
    S->base = (ElemType*)malloc(StackInitSize * sizeof(ElemType));
    if (!S->base) {
        exit(0);
    }
    S->top = S->base; /// 栈顶与栈底相同
    S->stacksize = StackInitSize; // 栈的最大长度等于初始长度
    return 1;
}

// 判断栈是否为空,只需要判断栈顶指针与栈底指针是否相同即可
Status StackEmpty(SqStack* S) {
    return S->base == S->top;
}

//获取栈的实际长度,栈顶减去栈底指针即为栈的长度
Status StackLength(SqStack* S) {
    if (S->top == S->base) {
        return 0;
    }
    return (Status)(S->top - S->base);
}

// 获取栈顶的元素,参数e用来存放栈顶的元素
Status GetTop(SqStack* S, int  &e) {
    if (S->top == S->base) {
        return 0;
    }
    e = *(S->top - 1);
    return e;
}

// 进栈,参数e是要进栈的元素
Status Push(SqStack* S, int  &e) {
    // 若栈的最大长度不会够用时,重新开辟,增大长度
    if (S->top - S->base >= S->stacksize) {
        S->base = (ElemType*)realloc(S->base, (S->stacksize + StackIncrement) * sizeof(ElemType));
        if (!S->base) {
            return 0;
        }
        // 栈顶指针为栈底指针加上栈之前的最大长度
        S->top = S->base + S->stacksize;
        // 栈当前的最大长度等于栈之前的最大长度与增加的长度之和
        S->stacksize += StackIncrement;
    }
    *S->top++ = e; // 先赋值,后栈顶指针上移
    return e;
}

// 出栈,参数e用来存放出栈的元素
Status Pop(SqStack* S, int &e) {
    if (S->base == S->top) {
        return 0;
    }
    e = *--S->top; // 栈顶指针先下移,后赋值
    return e;
}

// 销毁栈,释放栈空间,栈顶栈底指针置为NULL,长度置为0
Status DestroyStack(SqStack* S) {
    free(S->base);
    S->base = S->top = NULL;
    S->stacksize = 0;
    return 1;
}

// 遍历栈,依次打印每个元素
Status TraverseStack(SqStack* S) {
    ElemType* p;

    if (S->top == S->base) {
        printf("Stack is NULL.\n");
        return 0;
    }
    p = S->top;
    // 由栈顶依次向下遍历
    while (p > S->base) {
        p--;
        printf("%d ", *p);
    }
    printf("\n");
    return 1;
}

int main() {
    SqStack q, * S;
    S = &q;

    int i, n, e;

    InitStack(S);

    printf("输入栈的长度:\n");
    scanf("%d", &n);

    for (i = 1; i <= n; i++) {
        scanf("%d", &e);
        Push(S, e);
    }
    printf("是否为空栈\n");

    if (StackEmpty(S)) {
        printf("Yes!\n");
    }
    else {
        printf("No!\n");
    }
    printf("栈的长度是 %d.\n", StackLength(S));

    printf("遍历这个栈:\n");
    TraverseStack(S);

    GetTop(S, e);
    printf("栈顶元素为 %d.\n", e);

    printf("输入一个入栈的数 :\n");
    scanf("%d", &e);
    Push(S, e);
    printf("新的栈为 :\n");
    TraverseStack(S);

    printf("删除栈顶的数 : ");
    e = Pop(S, e);
    printf("%d\n", e);

    printf("新的栈为 :\n");
    TraverseStack(S);

    printf("销毁栈 :\n");
    DestroyStack(S);
    TraverseStack(S);

    return 0;
}

四,栈的应用

在这里插入图片描述
思路如下:
1.利用一个栈结构保存每个出现的左括号,当遇到右括号时,从栈中弹出左括号,检验匹配情况。
2.在检验过程中,若遇到以下几种情况之一,就可以得出括号不匹配的结论。
(1)当遇到某一个右括号时,栈已空,说明到目前为止,右括号多于左括号;
(2)从栈中弹出的左括号与当前检验的右括号类型不同,说明出现了括号交叉情况;
(3)算术表达式输入完毕,但栈中还有没有匹配的左括号,说明左括号多于右括号。

代码如下:

bool isValid(char * s){
    int length = strlen(s);     //求出字符串s的长度
    
    char Stack[length];         //定义一个顺序栈
    int top = -1;               //初始化栈

    //从左往右扫描字符串s
    for(int i = 0; i < length; i++){                        
        if(s[i] == '(' || s[i] == '[' || s[i] == '{'){    
         //扫描到“左括号”
            Stack[++top] = s[i];                           
         //将“左括号”入栈
        }else{ 
            if(top == -1)
                return false;           
       //扫描到“右括号”且栈为空,则括号匹配失败(“右括号”为单身)

            char topElem; 
            topElem = Stack[top--];     
            //出栈一个元素并赋值给topElem
            if(s[i] == ')' && topElem != '(')
                return false;                   //左右括号不匹配
            if(s[i] == ']' && topElem != '[')
                return false;                   //左右括号不匹配
            if(s[i] == '}' && topElem != '{')
                return false;                   //左右括号不匹配
        }
    }

    if(top != -1)
        return false;    
      //扫描到完字符串s后栈不空,则括号匹配失败(“左括号”为单身)
    return true;
   
}
  • 15
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值