一.栈
特点:栈为后进先出类型
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;
}