数据结构(顺序栈,链栈,应用题3个)

本文介绍了C语言中顺序栈和链栈的数据结构,包括初始化、插入和删除操作。还涉及了左分隔符和右分隔符的匹配问题,以及如何使用栈实现大数相加的算法。最后展示了用栈模拟递归过程的示例。
摘要由CSDN通过智能技术生成


顺序栈
#include <string.h>
#include <iostream>
using namespace std;
#define STACKMAX 80
#define STACKADD 10

typedef int SElemtype;

typedef struct {
    int *top;
    int *base;
    int stacksize;
} Sqstack;

bool initstack(Sqstack &s) {
    s.base = (int *)malloc(STACKMAX * sizeof(int));
    if (!s.base) {
        return 0;
    }
    s.top = s.base;
    s.stacksize = STACKMAX;
    return 1;
}

bool push(Sqstack &s, int e) {
    if (s.top - s.base >= s.stacksize) {
        s.base = (int *)realloc(s.base, (s.stacksize + STACKADD) * sizeof(int));
        if (!s.base) {
            return 0;
        }
        s.top = s.base + s.stacksize;
        s.stacksize += STACKADD;
    }
    *s.top++ = e;
    return 1;
}

bool pop(Sqstack &s, int &e) {
    if (s.top == s.base) {
        return 0;
    }
    e = *s.top--;
    return 1;
}

//链栈
typedef struct Snode {
    int data;
    struct Snode *next;
} Snode, *linkstack;

bool initstacklist(linkstack &s) {
    s = (linkstack)malloc(sizeof(Snode));
    if (!s) {
        return 0;
    }
//    s->next = NULL;链栈出入都在栈顶,不去设置头节点,因此初始化没有这一步
    return 1;
}

int stacklength(linkstack s) {
    int length = 0;
    linkstack p = s;
    while (p) {
        p = p->next;
        length++;
    }
    return length;
}

bool pushstack(linkstack &s, int e) {
    linkstack p = (linkstack)malloc(sizeof(Snode));
    p->data = e;
    p->next = s -> next;
    s -> next = p;
    s = p;
    return 1;
}

bool popstack(linkstack &s, int &e) {
    if (s == NULL) {
        return 0;
    }
    linkstack p = s;
    e = p->data;
    s = p->next;
    free(p);
    return 1;
}
//Q1左右分隔符匹配问题,从左往右扫描待判断的C语言语句,如果左分隔符,把他压入栈中,如果是右分隔符,有两个情况1,当前栈非空,
//就弹出来左分隔符,看是否匹配.2,栈是空的,证明右分隔符多余,匹配失败。如果所有字符都读完发现栈还有东西,证明做分隔符多余,匹配失败
typedef char SElemtype[3];
int LEFT = 0;
int RIGHT = 1;
int OTHER = 2;

int verifyflag(char *str) { //判断符号类型的函数
    if (!strcmp("(", str) || !strcmp("[", str) || !strcmp("{", str)
            || !strcmp("/*", str)) { //这里strcmp函数,如果匹配上返回0,所以加取反符
        return LEFT;
    }
    if (!strcmp(")", str) || !strcmp("]", str) || !strcmp("}", str)
            || !strcmp("*/", str)) {
        return RIGHT;
    } else {
        return OTHER;
    }
}

bool matches(char *str1, char *str2) { //监测匹配的函数
    if ((!strcmp("(", str1) && !strcmp(")", str2)) || (!strcmp("{", str1) && !strcmp("}", str2)) || (!strcmp("[", str1)
            && !strcmp("]", str2)) || (!strcmp("/*", str1) && !strcmp("*/", str2))) {
        return true;
    } else {
        return false;
    }
}

bool Islegal(char *str) {
    if (str != NULL && strcmp(" ", str)) { //监测非空
        Sqstack S;
        initstack(S);
        for (int i = 0; i < strlen(str); i++) {
            char c = str[i];
            char t[3] = c; //下面str全部t代替
            //这里本应该先考虑/* */问题,这里先跳过
            if (verifyflag() == LEFT) {
                push(S, t);
            } else if (verifyflag() == RIGHT) {
                if (S.top = S.base) {
                    printf("错误,右运算符多余");
                } else {
                    SElemtype t1;
                    pop(stacksize, t1);
                    if (!matches(t, t1)) {
                        printf("匹配失败");
                        return 0;
                    }
                }
            }
        }
        if (S.base != S.top) {
            printf("左运算多余,失败");
            return 0;
        } else {
            printf("匹配成功");
            return 1;
        }
    } else {
        printf("运算符为空,失败");
        return 0;
    }
}


//Q2,大数相加问题用的栈链,

当数字超出long long 需要我们用字符串的形式,利用栈去实现大数的相加
//两个加数先从高位到底位依次压入两个栈中,如果钧非空,弹出栈顶元素相加,和存入到oartialSum中,若和有进位
//直接将进位,放到下1位运算,将个位数字压入到结果栈sum中,如果没有进位,直接压入sum;
//如果现在某个加数栈是空的,将另外一个依次弹出栈顶元素与进位相加,压入sum栈,如果最高位还有进位,最后将1
//,压入sum中(就是9999999的情况)。最后两个都空了那就是结果。

linkstack Numtrans(char *str) { //将str以单个字符压入栈中,并且删除空格
    linkstack S;
    initstacklist(S);
    for (int i = 0; i < strlen(str); i++) {
        char c = str[i]; //指定索引处的char值
        if (c == ' ') {
            continue;
        } else if ('0' <= c && c <= '9') {
            pushstack(S, c);
        } else {
            printf("有非数字的字符,失败");
            return 0;//书上写exit(-1);
        }

    }
    return S;
}

char *ADDbignumber(char *a, char *b) {
    linkstack sum;
    initstacklist(sum);
    linkstack sA = Numtrans(a);
    linkstack sB = Numtrans(b);
    int partialsum;
    bool isCarry = false;
    while (sA && sB) { //两个栈链非空
        int c1, c2;
        popstack(sA, c1);
        popstack(sB, c2);
        //直接写两个的和
        partialsum = c1 - '0' + c2 - '0';
        if (isCarry) {
            partialsum++;
            isCarry = false;
        }
        if (partialsum > 9) {
            partialsum -= 10;
            pushstack(sum, partialsum); //个位压入栈
            isCarry = true;
        } else {
            pushstack(sum, partialsum);
        }
    }
    linkstack temp = (sA) ? sA : sB; //temp指向非空的
    while (temp) {
        int t;
        if (isCarry) {
            popstack(temp, t);
            t = t - '0';
            ++t;
            if (t > 9) {
                t -= 10;
                pushstack(sum, t);
            } else {
                pushstack(sum, t);
                isCarry = false;
            }
        } else {
            popstack(temp, t - '0');
            pushstack(sum, t);

        }
    }
//    最后考虑特殊的999999
    if (isCarry) {
        popstack(temp, 1);
        isCarry = false;
    }


    char str[100];
    int i;
    while (sum) { //栈中元素转化为字符串
        int e;
        popstack(sum, e);
        str[i++] = e + '0'; //整数变成字符
    }
    str[i] = '\0'; //结果加上结束符
    return str;
}

//Q3用栈实现递归

typedef struct {
    int n;
    double val;
} selemtype;

double p(int n, double x) {
    selemtype e;
    Sqstack S;
    initstack(S);
    double f1=1;
    double f2=2*x;
    if(n==0){
        return 1;
    }
    for(int i=n;i>=2;i--){
        e.n=i;
        e.val=0;
        push(S,e);
    }
    while(!StackEmpty(S)){
        pop(S,e);
        e.val=2*x*f2-2*(e.n-1)*f1;
        f1=f2;
        f2=e.val;
    }
      return f2;
}
 

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值