用栈实现 链表反转、多项式运算

目录

1、反转链表

2、检查括号是否匹配

3、中缀Infix,前缀prefix,后缀suffix

 4、中缀表达式 转 后缀表达式

5、简单的多项式运算

6、完整代码+运行截图


1、反转链表

 /*
 * 一般不建议像下面这样写,我是图省事,直接用之前的代码
 * e = (ElemTYpe)tmp;
 *  tmp->next = (SNode *) Top(S);
 *  最好在栈的数据结构中定义struct Node *类型的变量
 */

void ReverseList(SList *LL,SList S){
    ElemTYpe e;
    SNode *tmp = *LL;
    //将链表的地址全部压入栈中
    while (tmp != NULL){
        e = (ElemTYpe)tmp;
        Push(e,&S);
        tmp = tmp->next;
    }
    //拿到链表的最后一个地址
    tmp = (SNode *) Top(S);
    *LL = tmp;
    Pop(&S);
    //依次拿到后续地址
    while(IsEmpty(S) != 1){
        tmp->next = (SNode *) Top(S);
        Pop(&S);
        tmp = tmp->next;
    }
    tmp->next = NULL;
}

2、检查括号是否匹配

void Match(SList S,char *exp) {
    char e;
    while (*exp != '\0') {
        e = *exp;
        exp++;
        switch (e) {
            case '(':
            case '[': {
                Push((int) e, &S);
                break;
            }
            case ')': {
                if (IsEmpty(S) !=1 && (char) Top(S) == '('){
                    Pop(&S);
                    break;
                }
                else{
                    printf("括号匹配错误\n");
                    return;
                }
            }
            case ']': {
                if ( IsEmpty(S) !=1  &&(char) Top(S) == '[' ){
                    Pop(&S);
                    break;
                }
                else{
                    printf("括号匹配错误\n");
                    return;
                }
            }
        }
    }
    if (IsEmpty(S)) {
        printf("括号匹配正确\n");
    }
    else{
        printf("括号匹配错误\n");
    }
}

3、中缀Infix,前缀prefix,后缀suffix

中缀表达式 变 后缀表达式

中缀表达式 变 前缀表达式

 图片来源:https://www.bilibili.com/video/BV1Fv4y1f7T1?p=20
 

视频的思路非常清晰,就是没代码

 4、中缀表达式 转 后缀表达式

//优先级高的运算符一定是放在前面的
void InfixToSuffix(SList S,char *infix_exp,char *Suffix_exp){

    //首先判断括号匹配
    printf("中缀表达式:%s\n",infix_exp);
    if(Match(S,infix_exp)){
        printf("括号匹配正确\n");
    }
    else{
        printf("括号匹配错误\n");
        return;
    }

    char e;
    while(*infix_exp != '\0'){
        e = *infix_exp;
        //只要是”(”一定压入栈
        if(e == '('){
            Push((int)e,&S);
        }
        //当是乘"*"或除"/" 先判断栈顶元素,如果是乘除,则先出栈再压入栈
        else if((e == '*' || e== '/')  ) {
            if( IsEmpty(S) !=1 &&  ((char)Top(S) == '*' || (char)Top(S) == '/')){
                *Suffix_exp = (char)Top(S);
                Suffix_exp++;
                Pop(&S);

                Push((int)e,&S);
            }else{
                Push((int)e,&S);
            }
        }
        //当是加"+"或减"-" 先判断栈顶元素,除了"(",一律先出栈再压入栈
        else if(e == '+' || e== '-'){
            if(IsEmpty(S) !=1  &&  (char)Top(S) != '('){
                *Suffix_exp = (char)Top(S);
                Suffix_exp++;
                Pop(&S);

                Push((int)e,&S);
            } else{
                Push((int)e,&S);
            }
        }
        //括号里的运算符一律出栈
        else if(e == ')'){
            while((char)Top(S) != '('){
                *Suffix_exp = (char)Top(S);
                Suffix_exp++;

                Pop(&S);
            }
            Pop(&S);
        }
        //数字直接放入数组
        else{
            *Suffix_exp = e;
            Suffix_exp++;
        }
        infix_exp++;
    }
    //判断栈里是否还有运算符
    while(IsEmpty(S) != 1){
        *Suffix_exp = (char)Top(S);
        Pop(&S);
        Suffix_exp++;
    }
    *Suffix_exp = '\0';
}

5、简单的多项式运算

ElemTYpe Polynomial(SList S,char *infix_exp){

    //将前缀表达式转成后缀表达式
    int len = strlen(infix_exp);
    char Suffix_exp[len];
    InfixToSuffix(S,infix_exp,Suffix_exp);
    char *exp =  Suffix_exp;

    printf("后缀表达式:%s\n",exp);
    char e;
    ElemTYpe tmp; //临时保存运算的值
    while(*exp != '\0'){
        e = *exp;
        //数字统统入栈
        if( e == '*' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)*tmp;
            Pop(&S);

            Push(tmp,&S);
        }
        else if( e == '/' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)/tmp;
            Pop(&S);

            Push(tmp,&S);
        }
        else if( e == '+' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)+tmp;
            Pop(&S);

            Push(tmp,&S);
        }
        else if( e == '-' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)-tmp;
            Pop(&S);

            Push(tmp,&S);
        }else{
            //atoi(&e) 字符数字转整型数字
            Push(atoi(&e),&S);
        }
        exp++;
    }

    return tmp;
}

6、完整代码+运行截图

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

typedef int ElemTYpe;
//栈的数据结构
typedef struct SNode{
    struct SNode* next;
    ElemTYpe data;
}SNode,*SList;

//压栈
void Push(ElemTYpe e,SList *S);
//获取栈顶元素
ElemTYpe Top(SList S);
//出栈
void Pop(SList *S);
//判断栈空
int IsEmpty(SList S);
//打印
void PrintList(SList S);

//反转链表
void ReverseList(SList *LL,SList S);
//检查括号是否匹配 匹配1 不匹配0
int Match(SList S,char *exp);
//中缀表达式转后缀表达式
void InfixToSuffix(SList S,char *infix_exp,char *Suffix_exp);
//多项式运算
ElemTYpe Polynomial(SList S,char *infix_exp);

int main() {
    //栈
    SList S = NULL;
    ElemTYpe e = 7;

    //链表 不带头结点
    SList LL = NULL;

    for(int i = 6;i>0;i--){
        e--;
        Push(e,&LL);
    }
    printf("链表为:\n");
    PrintList(LL);
    ReverseList(&LL,S);
    printf("反转后:\n");
    PrintList(LL);


    //多项式的运算
    char infix_exp[] ={"3+1*(2+4*7)/5+6-8"};
    e = Polynomial(S,infix_exp);
    printf("%s 运算结果为 %d:\n",infix_exp,e);

    return 0;
}

void Push(ElemTYpe e,SList *S){
    SNode *tmp = (SNode *) malloc(sizeof(SNode));
    tmp->data = e;
    tmp->next = *S;
    *S = tmp;
   //printf("%d入栈\n",tmp->data);
}

ElemTYpe Top(SList S){

    if(S == NULL){
        printf("栈为空,无法获取栈顶元素\n");
        return 0;
    }
    else{
        return S->data;
    }
}

int IsEmpty(SList S){
    if(S == NULL)
        return 1;
    else
    return 0;
}

void Pop(SList *S){
    SNode *tmp;
    tmp = *S;
    if(tmp == NULL){
        printf("无法出栈,栈为空\n");
        return;
    }
    *S = (*S)->next;
    //printf("%d出栈\n",tmp->data);
    free(tmp);
}

void PrintList(SList S){
    while (S != NULL){
        printf("%d ",S->data);
        S = S->next;
    }
    printf("\n");
}

/*
 * 一般不建议像下面这样写,我是图省事,直接用之前的代码
 * e = (ElemTYpe)tmp;
 *  tmp->next = (SNode *) Top(S);
 *  最好在栈的数据结构中定义struct Node *类型的变量
 */
//反转链表
void ReverseList(SList *LL,SList S){
    ElemTYpe e;
    SNode *tmp = *LL;
    //将链表的地址全部压入栈中
    while (tmp != NULL){
        e = (ElemTYpe)tmp;
        Push(e,&S);
        tmp = tmp->next;
    }
    //拿到链表的最后一个地址
    tmp = (SNode *) Top(S);
    *LL = tmp;
    Pop(&S);
    //依次拿到后续地址
    while(IsEmpty(S) != 1){
        tmp->next = (SNode *) Top(S);
        Pop(&S);
        tmp = tmp->next;
    }
    tmp->next = NULL;
}

//检查括号是否匹配 匹配1 不匹配0
int Match(SList S,char *exp) {
    char e;
    while (*exp != '\0') {
        e = *exp;
        switch (e) {
            case '(':
            case '[': {
                Push((int) e, &S);
                break;
            }
            case ')': {
                if (IsEmpty(S) !=1 && (char) Top(S) == '('){
                    Pop(&S);
                    break;
                }
                else{
                    return 0;
                }
            }
            case ']': {
                if ( IsEmpty(S) !=1  &&(char) Top(S) == '[' ){
                    Pop(&S);
                    break;
                }
                else{
                    return 0;
                }
            }
        }
        exp++;
    }
    if (IsEmpty(S)) {
        return 1;
    }
    else{
        return 0;
    }
}

//中缀表达式转后缀表达式
//优先级高的运算符一定是放在前面的
void InfixToSuffix(SList S,char *infix_exp,char *Suffix_exp){

    //首先判断括号匹配
    printf("\n中缀表达式:%s\n",infix_exp);
    if(Match(S,infix_exp)){
        printf("括号匹配正确\n");
    }
    else{
        printf("括号匹配错误\n");
        return;
    }

    char e;
    while(*infix_exp != '\0'){
        e = *infix_exp;
        //只要是”(”一定压入栈
        if(e == '('){
            Push((int)e,&S);
        }
        //当是乘"*"或除"/" 先判断栈顶元素,如果是乘除,则先出栈再压入栈
        else if((e == '*' || e== '/')  ) {
            if( IsEmpty(S) !=1 &&  ((char)Top(S) == '*' || (char)Top(S) == '/')){
                *Suffix_exp = (char)Top(S);
                Suffix_exp++;
                Pop(&S);

                Push((int)e,&S);
            }else{
                Push((int)e,&S);
            }
        }
        //当是加"+"或减"-" 先判断栈顶元素,除了"(",一律先出栈再压入栈
        else if(e == '+' || e== '-'){
            if(IsEmpty(S) !=1  &&  (char)Top(S) != '('){
                *Suffix_exp = (char)Top(S);
                Suffix_exp++;
                Pop(&S);

                Push((int)e,&S);
            } else{
                Push((int)e,&S);
            }
        }
        //括号里的一律出栈
        else if(e == ')'){
            while((char)Top(S) != '('){
                *Suffix_exp = (char)Top(S);
                Suffix_exp++;

                Pop(&S);
            }
            Pop(&S);
        }
        //数字直接放入数组
        else{
            *Suffix_exp = e;
            Suffix_exp++;
        }
        infix_exp++;
    }
    //判断栈里是否还有运算符
    while(IsEmpty(S) != 1){
        *Suffix_exp = (char)Top(S);
        Pop(&S);
        Suffix_exp++;
    }
    *Suffix_exp = '\0';
}

//简单的多项式运算
ElemTYpe Polynomial(SList S,char *infix_exp){

    //将前缀表达式转成后缀表达式
    int len = strlen(infix_exp);
    char Suffix_exp[len];
    InfixToSuffix(S,infix_exp,Suffix_exp);
    char *exp =  Suffix_exp;

    printf("后缀表达式:%s\n",exp);
    char e;
    ElemTYpe tmp; //临时保存运算的值
    while(*exp != '\0'){
        e = *exp;
        //数字统统入栈
        if( e == '*' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)*tmp;
            Pop(&S);

            Push(tmp,&S);
        }
        else if( e == '/' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)/tmp;
            Pop(&S);

            Push(tmp,&S);
        }
        else if( e == '+' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)+tmp;
            Pop(&S);

            Push(tmp,&S);
        }
        else if( e == '-' ){
            tmp = Top(S);
            Pop(&S);
            tmp = Top(S)-tmp;
            Pop(&S);

            Push(tmp,&S);
        }else{
            //atoi(&e) 字符数字转整型数字
            Push(atoi(&e),&S);
        }
        exp++;
    }

    return tmp;
}

 只是自己写着玩练手的,逻辑有些混乱,还有很多细节没考虑

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值