栈
原理:先进后出。
顺序存储
#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;
}
}