数据结构(C语言)——第三章、栈与队列(1)栈


一、顺序栈

//
// Created by ASUS on 2021/8/26.
//
#include <iostream>

typedef int ElemType;

#define MaxSize 10  //定义栈中元素的最大个数
typedef struct{
    ElemType data[MaxSize];  //静态数组中存放栈中元素
    int top;  //栈顶指针
}SqStack;




//初始化栈
bool InitStack(SqStack &S) {
    S.top = -1;  //初始化栈顶指针   |  S.top = 0;
}

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

//新元素入栈
bool Push(SqStack &S, ElemType x){
    if(S.top == MaxSize-1)  //栈满,报错   |   S.top == MaxSize
        return false;
    S.top = S.top + 1;  //指针先加1
    S.data[S.top] = x;  //新元素入栈 这两句等价于S.data[++S.top] = x;  |  S.data[S.top++] = x
    return true;

}

//出栈操作
bool Pool(SqStack &S, ElemType &x){
    if(S.top == -1)  //栈空,报错   |  S.top == 0
        return false;
    x = S.data[S.top];  //栈顶元素先出栈
    S.top = S.top - 1;  //指针再减1  这两句等价于x = S.data[S.top--];   | x = S.data[--S.top];
    return true;
}

//获取栈顶元素
bool GetTop(SqStack S, ElemType &x){
    if(S.top == -1)  //栈空,报错   | S.top == 0
        return false;
    x = S.data[S.top];  //栈顶元素先出栈
    //S.top = S.top - 1;  //指针再减1  这一步不要!!!
    return true;
}

int main() {
    //声明一个顺序栈
    SqStack S;
    //初始化一个空栈
    printf("初始化栈是否成功:%s\n", InitStack(S) ? "是" : "否");
    //判空
    printf("栈是否为空:%s\n", StackEmpty(S) ? "是" : "否");
    //push(赋值)
    printf("开始赋值\n");
    for(int i = 0; i < 5; i++){
        if(Push(S, i))
            continue;
        else
            break;
    }
    //判空
    printf("栈是否为空:%s\n", StackEmpty(S) ? "是" : "否");

    //获取栈顶元素
    int x;
    GetTop(S, x);
    printf("栈顶元素为:%d\n", x);

    //出栈
    printf("开始出栈:");
    for(int i = 0; i < 5; i++){
        Pool(S, x);
        printf("%d ", x);
    }
    printf("\n");

    //判空
    printf("栈是否为空:%s\n", StackEmpty(S) ? "是" : "否");

    return 0;
}


二、共享栈

//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 共享栈操作
//
#include<stdio.h>
#define MaxSize 10  //定义共享栈中元素的最大个数
#define ElemType int

//共享栈的类型定义
typedef struct{
    ElemType data[MaxSize];  //静态数组存放栈中元素
    int top1;  //1号栈顶指针
    int top2;  //2号栈顶指针
} ShStack;

/*函数声明*/
void InitShStack(ShStack& S);				//1.初始化共享栈
bool Stack1Empty(ShStack S);				//2. 1号栈判空
bool Stack2Empty(ShStack S);				//2. 2号栈判空
bool Push1(ShStack& S, ElemType x);			//3. 1号栈入栈
bool Push2(ShStack& S, ElemType x);			//4. 2号栈入栈
bool Pop1(ShStack& S, ElemType& x);			//5. 1号栈出栈
bool Pop2(ShStack& S, ElemType& x);			//6. 2号栈出栈
bool GetTop1(ShStack S, ElemType& x);		//7. 1号栈读取栈顶元素
bool GetTop2(ShStack S, ElemType& x);		//8. 2号栈读取栈顶元素

//1.初始化共享栈
void InitShStack(ShStack &S){
    S.top1 = -1;      //1号栈顶指针初始化为-1
    S.top2 = MaxSize; //1号栈顶指针初始化为MaxSize
}

//2.1号栈判空
bool Stack1Empty(ShStack S){
    return (S.top1 == -1);
}

//3.2号栈判空
bool Stack2Empty(ShStack S){
    return (S.top2 == MaxSize);
}

//4.1号栈入栈
bool Push1(ShStack &S, ElemType e){
    if(S.top1 + 1 == S.top2)  //栈满
        return false;
    S.data[++S.top1] = e;
    return true;
}

//5.2号栈入栈
bool Push2(ShStack &S, ElemType e){
    if(S.top1 + 1 == S.top2)  //栈满
        return false;
    S.data[--S.top2] = e;
    return true;
}

//6.1号出栈操作
bool Pop1(ShStack &S, ElemType &e){
    if(S.top1 == -1)  //1号栈空
        return false;
    e = S.data[S.top1--];
    return true;
}

//7.2号出栈操作
bool Pop2(ShStack &S, ElemType &e){
    if(S.top2 == MaxSize)  //2号栈空
        return false;
    e = S.data[S.top2++];
    return true;
}

//8.1号读取栈顶元素
bool GetTop1(ShStack S, ElemType &e){
    if(S.top1 == -1)  //1号栈空
        return false;
    e = S.data[S.top1];
    return true;
}


//9.2号读取栈顶元素
bool GetTop2(ShStack S, ElemType &e){
    if(S.top2 == MaxSize)  //2号栈空
        return false;
    e = S.data[S.top2];
    return true;
}


int main(){
    //声明一个共享栈
    ShStack S;

    //初始化共享栈
    InitShStack(S);

    /*1号栈基本操作*/
    //1号栈-判空
    printf("当前1号栈是否为空:%s \n", Stack1Empty(S)?"是":"否");

    //1号栈-入栈
    ElemType e11;
    printf("请输入1号栈入栈元素的值:");
    scanf("%d",&e11);
    if(Push1(S, e11))
        printf("1号栈新元素入栈成功!\n");
    else
        printf("共享栈已满,1号栈新元素入栈失败!\n");

    //1号栈-读取栈顶元素
    ElemType e12;
    if(GetTop1(S, e12))
        printf("获取1号栈栈顶元素成功!栈顶元素为:%d\n", e12);
    else
        printf("1号栈已空,读取栈顶元素失败!\n");

    //1号栈-出栈
    ElemType e13;
    if(Pop1(S, e13))
        printf("1号栈栈顶元素出栈成功!栈顶元素为:%d\n", e13);
    else
        printf("1号栈已空,栈顶元素出栈失败!\n");

    //1号栈-再次读取栈顶元素
    ElemType e14;
    if(GetTop1(S, e14))
        printf("获取1号栈栈顶元素成功!栈顶元素为:%d\n", e14);
    else
        printf("1号栈已空,读取栈顶元素失败!\n");


    /*2号栈基本操作*/
    //2号栈-判空
    printf("当前2号栈是否为空:%s \n", Stack2Empty(S)?"是":"否");

    //2号栈-入栈
    ElemType e21;
    printf("请输入2号栈入栈元素的值:");
    scanf("%d",&e21);
    if(Push2(S, e21))
        printf("2号栈新元素入栈成功!\n");
    else
        printf("共享栈已满,2号栈新元素入栈失败!\n");

    //1号栈-读取栈顶元素
    ElemType e22;
    if(GetTop1(S, e12))
        printf("获取2号栈栈顶元素成功!栈顶元素为:%d\n", e22);
    else
        printf("2号栈已空,读取栈顶元素失败!\n");

    //2号栈-出栈
    ElemType e23;
    if(Pop2(S, e23))
        printf("2号栈栈顶元素出栈成功!栈顶元素为:%d\n", e23);
    else
        printf("2号栈已空,栈顶元素出栈失败!\n");

    //2号栈-再次读取栈顶元素
    ElemType e24;
    if(GetTop2(S, e24))
        printf("获取2号栈栈顶元素成功!栈顶元素为:%d\n", e24);
    else
        printf("2号栈已空,读取栈顶元素失败!\n");



    return 0;
}

三、链栈

1.不带头结点
//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 链栈(不带头结点)操作
//
#include<stdio.h>
#include<stdlib.h>
#define ElemType int

//链栈类型定义
typedef struct LinkStackNode{
    ElemType data;  //数据域
    struct LinkStackNode *next;  //指针域
}SNode, *LiStack;

//函数声明
/*函数声明*/
bool InitLinkStack(LiStack& S);			//1.初始化链栈
bool LiStackEmpty(LiStack S);			//2.判空
bool Push(LiStack& S, ElemType e);		//3.入栈
bool Pop(LiStack& S, ElemType& e);		//4.出栈
bool GetTop(LiStack S, ElemType& e);	//5.读取栈顶元素

//1.初始化链栈(不带头结点)
bool InitLinkStack(LiStack &S){
    S = NULL;  //初始化为空,暂时没有任何节点
    return true;
}

//2.判空
bool LiStackEmpty(LiStack S){
    return (S == NULL);
}

//3.入栈
bool Push(LiStack& S, ElemType e){
    SNode *p = (SNode *)malloc(sizeof(SNode));
    if(p == NULL)
        return false;//内存分配失败
    p->data = e;
    p->next = S;
    S= p;
    return true;
}

//4.出栈
bool Pop(LiStack& S, ElemType& e){
    if(S == NULL)
        return false;//栈空
    SNode *p;
    p = S;
    e = p->data;
    S = p->next;
    free(p);
    return true;
}

//5.读取栈顶元素
bool GetTop(LiStack S, ElemType& e){
    if(S == NULL)
        return false;//栈空
    e = S->data;
    return true;
}

int main(){
    //声明一个链栈
    LiStack S;

    //初始化栈
    InitLinkStack(S);

    //判空
    printf("当前栈是否为空:%s \n", LiStackEmpty(S)?"是":"否");

    //入栈操作
    ElemType e1;
    printf("请输入待入栈元素的值:");
    scanf("%d", &e1);
    if(Push(S, e1))
        printf("新元素入栈成功!\n");
    else
        printf("内存分配失败!\n");

    //读取栈顶元素
    ElemType e2;
    if(GetTop(S, e2))
        printf("读取栈顶元素成功!栈顶元素为:%d\n",e2);
    else
        printf("栈空,读取栈顶元素失败!\n");

    //出栈
    ElemType e3;
    if(Pop(S, e3))
        printf("出栈成功,出栈的栈顶元素为:%d \n", e3);
    else
        printf("栈空,出栈失败!\n");

    //读取栈顶元素
    ElemType e4;
    if(GetTop(S, e4))
        printf("读取栈顶元素成功!栈顶元素为:%d\n",e4);
    else
        printf("栈空,读取栈顶元素失败!\n");


    return 0;
}

2.带头结点
//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 链栈(带头结点)操作
//

#include<stdio.h>
#include<stdlib.h>
#define ElemType int

//链栈类型定义
typedef struct LinkStackNode{
    ElemType data;  //数据域
    struct LinkStackNode *next;  //指针域
}SNode, *LiStack;

//函数声明
/*函数声明*/
bool InitLinkStack(LiStack& S);			//1.初始化链栈
bool LiStackEmpty(LiStack S);			//2.判空
bool Push(LiStack& S, ElemType e);		//3.入栈
bool Pop(LiStack& S, ElemType& e);		//4.出栈
bool GetTop(LiStack S, ElemType& e);	//5.读取栈顶元素

//1.初始化链栈(带头结点)
bool InitLinkStack(LiStack &S){
    S = (SNode *) malloc(sizeof(SNode));
    if(S == NULL)
        return false;  //内存不足,分配失败
    S->next = NULL;  //头结点之后,暂时没有任何节点
    return true;
}

//2.判空
bool LiStackEmpty(LiStack S){
    return (S->next == NULL);
}

//3.入栈
bool Push(LiStack& S, ElemType e){
    SNode *p = (SNode *)malloc(sizeof(SNode));
    if(p == NULL)
        return false;//内存分配失败
    p->data = e;
    p->next = S->next;
    S->next = p;
    return true;
}

//4.出栈
bool Pop(LiStack& S, ElemType& e){
    if(S->next == NULL)
        return false;//栈空
    SNode *p;
    p = S->next;
    e = p->data;
    S->next = p->next;
    free(p);
    return true;
}

//5.读取栈顶元素
bool GetTop(LiStack S, ElemType& e){
    if(S == NULL)
        return false;//栈空
    e = S->next->data;
    return true;
}

int main(){
    //声明一个链栈
    LiStack S;

    //初始化栈
    InitLinkStack(S);

    //判空
    printf("当前栈是否为空:%s \n", LiStackEmpty(S)?"是":"否");

    //入栈操作
    ElemType e1;
    printf("请输入待入栈元素的值:");
    scanf("%d", &e1);
    if(Push(S, e1))
        printf("新元素入栈成功!\n");
    else
        printf("内存分配失败!\n");

    //读取栈顶元素
    ElemType e2;
    if(GetTop(S, e2))
        printf("读取栈顶元素成功!栈顶元素为:%d\n",e2);
    else
        printf("栈空,读取栈顶元素失败!\n");

    //出栈
    ElemType e3;
    if(Pop(S, e3))
        printf("出栈成功,出栈的栈顶元素为:%d \n", e3);
    else
        printf("栈空,出栈失败!\n");

    //读取栈顶元素
    ElemType e4;
    if(GetTop(S, e4))
        printf("读取栈顶元素成功!栈顶元素为:%d\n",e4);
    else
        printf("栈空,读取栈顶元素失败!\n");

    return 0;
}

四、栈的应用

括号匹配测试,递归(阶乘,斐波那契数列)
//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 栈的应用——【括号匹配】、【表达式求值】、【递归】
//               补充:此处是用的顺序栈
//

#include<stdio.h>
#include<string.h>
#define MaxSize 10			//定义栈中元素的最大个数
#define ElemType char

typedef struct {
    ElemType data[MaxSize];		//静态数组存放栈中元素
    int top;					//栈顶指针,一般来说存放数组的下标
}SeqStack;

/*函数声明*/
void InitStack(SeqStack& S);				//1.初始化栈
bool StackEmpty(SeqStack S);				//2.判空
bool Push(SeqStack& S, ElemType x);			//3.入栈
bool Pop(SeqStack& S, ElemType& x);			//4.出栈

/*基本操作*/
//1.初始化栈
void InitStack(SeqStack& S) {
    S.top = -1;		//初始化栈顶指针为-1
}
//2.判空
bool StackEmpty(SeqStack S) {
    return (S.top == -1);
}
//3.入栈操作:新元素入栈(先加再存)
bool Push(SeqStack& S, ElemType x) {
    if (S.top == MaxSize - 1)		//栈满,报错
        return false;
    S.data[++S.top] = x;	//栈顶指针+1,栈顶元素入栈
    return true;
}
//4.出栈操作:栈顶元素出栈(先取再减)
bool Pop(SeqStack& S, ElemType& x) {
    if (S.top == -1)		//栈空,报错
        return false;
    x = S.data[S.top--];	//栈顶元素出栈,栈顶指针-1
    return true;
}

/*栈的应用*/
//1.括号匹配
bool BracketMatch(char str[], int length){
    SeqStack S;
    InitStack(S);
    for(int i = 0; i < length; i++){
        if(str[i]=='(' || str[i]=='[' || str[i]=='{')//扫描到左括号,入栈
            Push(S, str[i]);
        else{//扫描到右括号
            if(StackEmpty(S)) //栈空
                return false;  //栈空,匹配失败
            else{//栈非空
                ElemType topElem;
                Pop(S, topElem); //栈顶元素出栈
                //左右括号不匹配,匹配失败
                if(str[i]==')' && topElem!='(')
                    return false;
                if(str[i]==']' && topElem!='[')
                    return false;
                if(str[i]=='}' && topElem!='{')
                    return false;
            }
        }
    }
    /*
     * 括号数组遍历已完成:
     *     1.若此时栈非空,左括号单身,匹配失败
     *     2.若此时栈空,则匹配成功
     * */
    return StackEmpty(S);
}
void TestBracketMatch(){
    char s1[] = {'(','[','{','}','(',')',']',')'};		//成功匹配
    char s2[] = {'{','[','(',')','}',']','(',')'};		//匹配失败
    if (BracketMatch(s1, 8))  //length是字符串的长度
        printf("匹配成功!\n");
    else
        printf("匹配失败!\n");

    if (BracketMatch(s2, 8))
        printf("匹配成功!\n");
    else
        printf("匹配失败!\n");
}

//2.表达式求值 前缀,中缀,后缀 【待完成】

//3.递归
int Factorial(int n){
    if(n==0 || n==1)
        return 1;
    else
        return n * Factorial(n-1);
}

//4.斐波那契数
int Fib(int n){
    if(n == 0)
        return 0;
    else if(n == 1)
        return 1;
    else
        return Fib(n-1) + Fib(n-2);
}

int main(){
    //括号匹配测试
    //TestBracketMatch();

    //递归测试1 阶乘
    int a = Factorial(3);
    printf("%d\n",a);

    //递归测试2 斐波那契测试
    int b = Fib(3);
    printf("%d\n",b);

    return 0;
}

参考来源:
数据结构代码参考博客
《王道数据结构》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值