数据结构-线性

本文介绍了栈和队列的基本原理和实现,包括顺序存储和链式存储。详细讲解了栈的先进后出特性,以及在四则运算表达式求值中的应用。同时,探讨了如何将中缀表达式转换为后缀表达式,以及后缀表达式的计算方法。此外,还涵盖了循环队列的概念和链式存储结构在队列实现中的运用。
摘要由CSDN通过智能技术生成

原理:先进后出。
顺序存储

#include<stdio.h>
#define max 10000
typedef struct stack
{
    int data[max];
    int top;
}Stack;
int insert(Stack *s,int n);
int main()
{
    Stack s;
    s.top=-1;//表示没有数。
    int n,i;
    scanf("%d",&n);
    if(insert(&s,n)==0)
        printf("无法插入数据,栈满\n");
    for(i=s.top;i>=0;i--)
        printf("%d ",s.data[i]);
}
int insert(Stack *s,int n)
{
    int i;
    if(s->top==max-1)
        return 0;
    s->top++;
    s->data[s->top]=n;
    return 1;
}
int del(Stack *s)
{
    if(s->top<0)
        return 0;
    s->top--;
    return 1;
}

栈共享空间
定义了两栈顶,判断栈是否满的时候是top1+1!=top2,进行处理的时候要判断是对那个栈的处理。
链式存储

#include<stdio.h>
#include<stdlib.h>
#define max 10000
typedef struct stack
{
    int data;
    struct stack *next;
}Stack;
typedef struct list
{
    Stack *top;
    int count;
}List;
int insert(List *s,int n);
int creat(List *s,int n);
int del(List *s);
int main()
{
    List s;
    Stack *p;
    int n;
    scanf("%d",&n);
    creat(&s,n);
    p=s.top;
    while(p)
    {
        printf("%d ",p->data);
        p=p->next;
    }
}
int creat(List *s,int n)
{
    int i;
    Stack *p;
    s->count=0;
    s->top=0;
    for(i=0;i<n;i++)
    {
        p=(Stack *)malloc(sizeof(Stack));
        scanf("%d",&p->data);
        p->next=s->top;
        s->top=p;
    }
}
int insert(List *s,int n)
{
    Stack *p;
    p=(Stack *)malloc(sizeof(Stack));
    p->data=n;
    s->top->next=p;
    s->top=p;
}
int del(List *s)
{
    Stack *p;
    p=s->top;
    s->top=s->top->next;
    printf("%d\n",p->data);
    free(p);
}

栈的应用—四则运算表达式求值
后缀表达式计算:遇到数字进栈,遇到运算符出栈,将栈顶两数字运算
中缀表达式(也就是我们平时书写的样式)转后缀表达式
是数字就进放后缀的数组里面,如果接下来的运算符比栈顶运算符优先级低直接进栈,遇见括号就将括号里面的所有运算符出栈,如果没有比栈顶运算符优先级低的话将所有运算符出栈,并入栈当前运算符,最后判断栈内是否残留运算符,并将所有运算符出栈。

#include<stdio.h>
#include<ctype.h>
#define max 10000
typedef struct stack1
{
    float num[max];
    int top;
}Stack1;
int Switch(Stack1 *s,char *str1,int *str2);
float operation(Stack1 *s,int *str2,int num2);
int get(int *i,char *str2);
int main()
{
    Stack1 s;
    s.top=-1;
    char str1[max];
    int str2[max],num2;
    scanf("%s",str1);
    num2=Switch(&s,str1,str2);
    for(int i=0;i<num2;i++)
    {
        printf("%d ",str2[i]);
    }
    printf("\n----------------\n");
    printf("%f",operation(&s,str2,num2));
}
int Switch(Stack1 *s,char *str1,int *str2)//将中缀转换为后缀
{
    int i,j,k;
    for(i=0,k=0;str1[i];i++)
    {
        if(isdigit(str1[i]))
        {
            str2[k++]=get(&i,str1);//获得数字入栈
        }
        else
        {
            if(s->top==-1)
            {
                s->top++;
                s->num[s->top]=str1[i];
            }
            else
            {
                if(str1[i]==')')
                {
                    while(s->num[s->top]!='(')
                    {
                        str2[k++]=s->num[s->top--];
                    }
                    s->top--;//)不用入栈
                }//记得判断当栈顶为(时也要入栈
                else if(s->num[s->top]=='('||str1[i]=='('||(str1[i]=='/'||str1[i]=='*')&&(s->num[s->top]=='+'||s->num[s->top]=='-')||(s->num[s->top]=='*'||s->num[s->top]=='/')&&(str1[i]=='*'||str1[i]=='/'))
                {
                    s->top++;
                    s->num[s->top]=str1[i];
                }
                else
                {
                    while(s->top>=0//当为+或-在栈内是并且str1的也是+或-时全部出栈
                    {
                        str2[k++]=s->num[s->top--];
                    }
                    s->top++;
                    s->num[s->top]=str1[i];
                }
            }
        }
    }
    while(s->top>=0)//判断栈内是否有值,所有出栈
    {
        str2[k++]=s->num[s->top--];
    }
    return k;
}
float operation(Stack1 *s,int *str2,int num2)//后缀计算值
{
    int i;
    for(i=0;i<num2;i++)
    {
        if(str2[i]!='+'&&str2[i]!='-'&&str2[i]!='/'&&str2[i]!='*')//数字直接存入栈
        {
            s->top++;
            s->num[s->top]=str2[i];
        }
        else
        {   float a;
            switch(str2[i])//因为是栈所以用前面的运算栈顶数字
            {
                case '+':a=s->num[s->top-1]+s->num[s->top];s->num[--s->top]=a;break;
                case '-':a=s->num[s->top-1]-s->num[s->top];s->num[--s->top]=a;break;
                case '*':a=s->num[s->top-1]*s->num[s->top];s->num[--s->top]=a;break;
                case '/':a=s->num[s->top-1]/s->num[s->top];s->num[--s->top]=a;break;
            }
        }
    }
    return s->num[s->top];
}
int get(int *i,char *str2)//将字符数字变为整形
{
    int a=0;
    while(isdigit(str2[*i]))
    {
        a=a*10+(str2[*i]-'0');
        ++*i;
    }
    --*i;
    return a;
}

队列

原理:先进先出,删除数据在队头,插入数据在队尾。
顺序存储

#include<stdio.h>
#define max 10000
typedef struct queue
{
    int data[max];
    int rear,front;
}Queue;
void creat(Queue *s,int n);
void del(Queue *s);
int main()
{
    Queue s;
    int n;
    scanf("%d",&n);
    s.rear=s.front=0;
    creat(&s,n);
    del(&s);
    for(int i=s.front;i<s.rear;i++)
    {
        printf("%d ",s.data[i]);
    }
}
void creat(Queue *s,int n)//插入数据只能在队尾进行
{
    int i;
    for(i=0;i<n;i++)
    {
        scanf("%d",s->data+s->rear);
        s->rear++;
    }
}
void del(Queue *s)//删除数据只能在队头进行
{
    int i;
    for(i=s->front;i<s->rear-1;i++)
    {
        s->data[i]=s->data[i+1];
    }
    s->rear--;
}

循环队列
也就是将队列视为一个环,删除数据时移动的时front,不需要将后面的数据向前移动,如果到队列最后时再移动就是到第一个。
判断为空时:front=rear
判断队列满时:队列留了一个空间,不用来存放数据,用来判断队列满时,(rear+1)%max=front.
此时求队列长度就为:
(rear-front+max)%max
将front>rear和front<rear都考虑了。

int creat(Queue *s,int n)//插入数据只能在队尾进行
{
    int i;
    for(i=0;i<n;i++)
    {
        if((s->rear+1)%max==s->front)
            return 0;
        scanf("%d",s->data+s->rear);
        s->rear=(s->rear+1)%max;
    }
    return 1;
}

int del(Queue *s)//删除数据只能在队头进行
{
    if(s->front==s->rear)
    return 0;
    s->front=(s->front+1)%max;
    return 1;
}

链式存储

#include<stdio.h>
#include<stdlib.h>
typedef struct list
{
    int data;
    struct list *next;
}List;
typedef struct queue
{
    List *front,*rear;
}Queue;
void insert(Queue *s,int n);
int del(Queue *s);
int main()
{
    Queue s;
    List *p;
    int n;
    scanf("%d",&n);
    s.rear=s.front=0;
    insert(&s,n);
    p=s.front;
    while(p)
    {
        printf("%d ",p->data);
        p=p->next;
    }
}
void insert(Queue *s,int n)//插入数据只能在队尾进行
{
    List *p;
    p=(List *)malloc(sizeof(List));
    p->data=n;
    if(s->front==0)
    {
        p->next=s->front;
        s->rear=s->front=p;
    }
    else
    {
        p->next=s->rear->next;
        s->rear=p;
    }
}
int del(Queue *s)//删除数据只能在队头进行
{
    if(s->front==0)
        return 0;
    List *p;
    p=s->front;
    s->front=s->front->next;
    if(p==s->rear)//代表了只有一个节点所以尾赋值为NULL
    {
        s->rear=NULL;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值