C语言数据结构[栈和队列][括号匹配、中缀表达式运算]

一.栈

在这里插入图片描述
特点:栈为后进先出类型

1.链栈基础

解释:入栈采用头插法的方法;出栈通过读取链表第一个值就能删除,出栈时要返回删除的值

1.1 初始化

typedef struct student
{
    char data;
    struct student* next;
} NODE;
// 初始化
NODE* list_init()
{
    NODE* p= (NODE*)malloc(sizeof(NODE));
    p->data='/0';
    p->next=NULL;
    return p;
}

1.2 入栈

typedef struct student{
    int data;
    struct student* next;
}NODE;
// 初始化
NODE* list_init(){
    NODE* p= (NODE*)malloc(sizeof(NODE));
    p->data=0;
    p->next=NULL;
}

1.3 出栈

// 出栈->去掉第一个 0 1 并且返回值
char list_remove(NODE* p)
{
    NODE* death=p->next;
    p->next=death->next;
    char data=death->data;
    free(death);
    return data;
}

1.4 判断栈是否空

// 判断栈是否空
int list_subject(NODE* p){
    NODE* subject=p;
    if(subject->next==NULL){
        return 0;
    }else{
        return 1;
    }

}

1.5 打印

// 打印展示栈目前的情况
void list_printf(NODE* p){
    NODE* print=p->next;
    while(print){
        printf("%c\n",print->data);
        print=print->next;
    }
}

1.6 主程序

int main(){
    NODE* p=list_init();
    list_insert(p,120);
    list_insert(p,10);
    list_insert(p,30);
    list_remove(p);
    list_printf(p);
    return 0;
}

2.链栈实践

2.1 括号匹配

// 链栈
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
    char data;
    struct student* next;
} NODE;
// 初始化
NODE* list_init()
{
    NODE* p= (NODE*)malloc(sizeof(NODE));
    p->data='/0';
    p->next=NULL;
    return p;
}
// 入栈->头插法 0 1 2 3
void list_insert(NODE* p,char data)
{
    int i;
    NODE* node = (NODE*)malloc(sizeof(NODE));
    if(node)
    {
        node->data=data;
        node->next=p->next;
        p->next=node;
    }
    else
    {
        printf("分配已经失败,程序错误");
    }
}
// 出栈->去掉第一个 0 1 并且返回值
char list_remove(NODE* p)
{
    NODE* death=p->next;
    p->next=death->next;
    char data=death->data;
    free(death);
    return data;
}
// 打印展示栈目前的情况
void list_printf(NODE* p)
{
    NODE* print=p->next;
    while(print)
    {
        printf("%c\n",print->data);
        print=print->next;
    }
}
// 判断栈是否空
int list_subject(NODE* p)
{
    NODE* subject=p;
    if(subject->next==NULL)
    {
        return 0;
    }
    else
    {
        return 1;
    }

}
int main()
{
    int i=0,value_subject,value_subject_isnull;
    char temporary;
    NODE* p=list_init();
    char str[]="{[]()}";
    while(str[i])
    {
        if(str[i]=='{'||str[i]=='('||str[i]=='[')
        {
            list_insert(p,str[i]);
        }else{
            temporary= list_remove(p);
            if(str[i]==')'&&temporary=='('){
                value_subject=1;
            }else if(str[i]=='}'&&temporary=='{'){
                value_subject=1;
            }else if(str[i]==']'&&temporary=='['){
                value_subject=1;
            }else{
                value_subject=0;
                break;
            }
        }
        i++;
    }
    value_subject_isnull = list_subject(p);
    if(value_subject&&value_subject_isnull==0){
           printf("结果:语法正确");
    }else{
           printf("结果:语法错误");
    }
    return 0;
}

2.2 中缀表达式运算

思路:写出两个栈,分别为A和B,A栈只存数字,B栈存放有运算等级的符号。B栈顶部原则是最高级在顶部。当最高级在顶部,如果遇到低级的进入最高级就需要出来,取出A中的数据进行运算。当遇到界限符,优先遵守下面规则,一直加入直到闭合,然后取出括号进行运算

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// 数字
typedef struct studenta
{
    float data;
    struct studenta* next;
} Node_Number;
// 符号
typedef struct studentb
{
    char data;
    struct studentb* next;
} Node_Sign;
// 存放数字的栈
Node_Number* list_init_number();
void list_insert_number(Node_Number* p,float data);
float list_remove_number(Node_Number* p);
void list_printf_number(Node_Number* p);
// 存放符号的栈
Node_Sign* list_init_sign();
void list_insert_sign(Node_Sign* p,char data);
char list_remove_sign(Node_Sign* p);
void list_printf_sign(Node_Sign* p);
// 优先级
int grade(char data)
{
    if(data=='(')
    {
        return 4;
    }
    else if(data=='/')
    {
        return 3;
    }
    else if(data=='*')
    {
        return 2;
    }
    else if(data=='+'||data=='-')
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
// 判断是否要直接插入
int subject_grade(Node_Sign* p,char data)//1 2 ;+ - *
{
    if(p->next==NULL)
    {
        return 1;
    }
    else
    {
        if(p->next->data=='(')// 左括号优先级高的特殊情况,这样写是为了继续入栈
        {
            return 1;
        }
        else if(grade(data)>=grade(p->next->data))// 正常优先高遇到低要出
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}
float calculation(char n,float a,float b)
{
    float temporary;
    switch(n)
    {
    case '*':
        temporary=b*a;
        break;
    case '/':
        temporary=b/a;
        break;
    case '+':
        temporary=b+a;
        break;
    case '-':
        temporary=b-a;
        break;
    }
    return temporary;
}
int main()
{
    int i=0;
    char target[]="511.5+2*(3+5+4)*(5+6)/5+(5*3)";
    Node_Number* number=list_init_number();// 数据
    Node_Sign* sign=list_init_sign();// 运算符号
    while(target[i])
    {
        if(target[i]>'0'&&target[i]<'9')// 数字直接插入
        {
            float t=0;// 字符串转换
            while(target[i]>'0'&&target[i]<'9'||target[i]=='.')
            {
                if(target[i]=='.')
                {
                    i++;
                    int j=1;
                    while(target[i]>'0'&&target[i]<'9')
                    {

                        t=t+(float)(target[i]-'0')/pow(10,j);
                        j++;
                        i++;
                    }
                }
                else
                {
                    t = t*10+target[i]-'0';
                    i++;
                }

            }
            list_insert_number(number,t);
        }
        else // 符号
        {
            if(target[i]==')')
            {
                Node_Sign* p=sign->next;
                while(p->data!='(')
                {
                    char n=p->data;
                    float a=list_remove_number(number);
                    float b=list_remove_number(number);
                    float result=calculation(n,a,b);
                    list_insert_number(number,result);
                    p=p->next;
                    list_remove_sign(sign);
                }
                list_remove_sign(sign);// 移除左括号
            }
            else if(subject_grade(sign,target[i]))// 正常
            {
                list_insert_sign(sign,target[i]);
            }
            else  // 先删除再插入
            {
                // 移除
                while(grade(target[i])<grade(sign->next->data))
                {
                    char n=list_remove_sign(sign);
                    float a=list_remove_number(number);
                    float b=list_remove_number(number);
                    float result= calculation(n,a,b);
                    // 加入
                    list_insert_number(number,result);
                }
                list_insert_sign(sign,target[i]);
            }
            i++;
        }

    }
    Node_Sign* flag=sign->next;

    while(flag)
    {
        char n=flag->data;
        float a=list_remove_number(number);
        float b=list_remove_number(number);
        float result= calculation(n,a,b);
        list_insert_number(number,result);
        flag=flag->next;
        list_remove_sign(sign);
    }

    printf("result=%.2f",number->next->data);
    return 0;
}
// 存放数字
Node_Number* list_init_number()
{
    Node_Number* p= (Node_Number*)malloc(sizeof(Node_Number));
    p->data=0;
    p->next=NULL;
    return p;
}
void list_insert_number(Node_Number* p,float data)
{
    int i;
    Node_Number* node = (Node_Number*)malloc(sizeof(Node_Number));
    if(node)
    {
        node->data=data;
        node->next=p->next;
        p->next=node;
    }
    else
    {
        printf("分配已经失败,程序错误");
    }
}
float list_remove_number(Node_Number* p)
{
    Node_Number* death=p->next;
    p->next=death->next;
    float data=death->data;
    free(death);
    return data;
}
void list_printf_number(Node_Number* p)
{
    Node_Number* print=p->next;
    while(print)
    {
        printf("%f  %p\n",print->data,print->next);
        print=print->next;
    }
}
// 存放符号
Node_Sign* list_init_sign()
{
    Node_Sign* p= (Node_Sign*)malloc(sizeof(Node_Sign));
    p->data=0;
    p->next=NULL;
    return p;
}
void list_insert_sign(Node_Sign* p,char data)
{
    int i;
    Node_Sign* node = (Node_Sign*)malloc(sizeof(Node_Sign));
    if(node)
    {
        node->data=data;
        node->next=p->next;
        p->next=node;
    }
    else
    {
        printf("分配已经失败,程序错误");
    }
}
char list_remove_sign(Node_Sign* p)
{
    Node_Sign* death=p->next;
    p->next=death->next;
    int data=death->data;
    free(death);
    return data;
}
void list_printf_sign(Node_Sign* p)
{
    Node_Sign* print=p->next;
    while(print)
    {
        printf("%c 自己%p 下一个%p\n",print->data,print,print->next);
        print=print->next;
    }
}

二.队列

在这里插入图片描述
特点:先进先出类型

1.链队列

1.1 初始化

typedef struct student
{
    int data;
    struct student* pre;
    struct student* next;
} NODE;
// 初始化
NODE* list_init()
{
    NODE* p= (NODE*)malloc(sizeof(NODE));
    p->data='/0';
    p->pre=p;
    p->next=p;
    return p;
}

1.2 入列

// 入队列->头插法 0 1 2 3
void list_insert(NODE* p,int data)
{
    int i;
    NODE* node = (NODE*)malloc(sizeof(NODE));
    if(node)// 0 2 4
    {
        node->data=data;
        node->pre=p;
        node->next=p->next;
        p->next=node;
        node->next->pre=node;
        if(node->next==p) // 应对数据插到队尾,头节点pre的处理
        {
            p->pre=node;
        }
    }
    else
    {
        printf("分配已经失败,程序错误");
    }
}

1.3 出列

// 出队列->去掉尾部 0
void list_remove(NODE* p)
{
    NODE * tail=p->pre;// 选到最后一个
    tail->pre->next=p;
    p->pre=tail->pre;// 最后一个的前一个把指针指向开头
    free(tail);

}

1.4 打印

// 打印展示栈目前的情况
void list_printf(NODE* p)
{
    NODE* print=p->next;
    while(print!=p)
    {
        printf("%d\n",print->data);
        print=print->next;

    }
}

1.5 主程序

int main()
{
    NODE* p=list_init();
    list_insert(p,155);
    list_insert(p,15);
    list_insert(p,1);
    list_remove(p);
    list_printf(p);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值