栈
栈(stack)是仅限定在表尾进行插入和删除的线性表 栈就是一个线性表,只不过,栈的insert和delete 只能在表尾 普通的线性表,是不是可以在任意位置进行insert和delete LIFO:Last in first out 后进先出 栈顶(top):进行插入和删除操作一端 栈底(bottom) 栈其实是我们计算机科学当中,更多来说,是一种思想,“先进后出的思想”,在很多的算法或者应用当中, 需要用到“先进后出的思想”,我们就可以用栈来实现。 例子: 1、假设有一个栈S,入栈元素的顺序是ABCD,请问这四个元素的出栈顺序有哪些??总数是??
2、有五个元素,其入栈的次序为A,B,C,D,E,在各种可能的出栈的次序中,第一个出栈元素为C,并且第二个元素为D的出栈序列有哪几种?? cdeba cdbea cdbae 本质: 是一个“先进后出”(仅在表尾/栈顶那一段进行插入和操作的)线性表
栈的实现
存储结构(物理结构): 顺序结构:用一组地址连续的空间来存储数据元素 链式结构:用地址不连续的空间来存储数据元素,可能需要额外的开辟一些空间,来存储 “数据元素之间的逻辑关系”。 ----栈的基本操作----- InitStack 初始化一个栈 DestoryStack 销毁一个栈 ClearStack 清空一个栈 StackEmpty 判断一个栈是否为空 StackLength 返回栈中的元素的个数,也就是栈的长度 Push 元素入栈,把一个元素加入到栈中 Pop 出栈,把栈顶元素给干掉 GetTop 返回一个栈顶元素,但是不出栈顺序栈
seqStack 用一组地址连续的空间来存储数据元素 数组typedef int SElemType; typedef strcut SeqStack { //SElemType data[1024]; //data 用来存储栈中的元素 SElemType *data; //data 指向的空间用来存储栈中的元素 “动态数组” //data = malloc(maxlen*sizeof(SElemType)) ; int maxlen; //栈中最多可以存多少个元素 int top; //栈顶元素的下标 //-1 表示空栈 }SeqStack; #include<stdio.h> #include<stdlib.h> #include<string.h> #include"seqstack.h" /* @InitStack:初始化一个栈 @maxl:栈的最大空间 @rerurn:返回一个栈的指针 */ SeqStack* InitStack(int maxl) { SeqStack * stack=malloc(sizeof(SeqStack)); stack->maxlen=maxl; stack->data=malloc(maxl*sizeof(SElemtype)); stack->top=-1;//空栈 return stack; } /* @Push:入栈 @SeqStack* s:栈头 @SElemtype x:要入栈的元素 */ int Push(SeqStack* s,SElemtype x) { if(s==NULL||s->top==s->maxlen-1) { printf("栈溢出\n"); return 0;//入栈失败 } s->data[++s->top]=x; return 1;//入栈成功 } /* @Pop:出栈 @SeqStack* s:栈头 @SElemtype* e:要出栈的元素地址 */ int Pop(SeqStack* s,SElemtype *e) { if(s==NULL||s->top==-1) { return 0;//出栈失败 } *e=s->data[s->top--]; return 1; } //销毁一个栈 void DestoryStack(SeqStack* s) { if(s==NULL) return; free(s->data); free(s); } //清空一个栈 void ClearStack(SeqStack* s) { if(s==NULL) return; while(s->top!=-1) s->data[s->top--]=0; s->maxlen=0; } //判断一个栈是否为空 int StackEmpty(SeqStack* s) { if(s==NULL||s->top==-1) return 0;//栈为空 else return 1;//栈不为空 } //返回一个栈的元素个数 int StackLength(SeqStack* s) { if(s==NULL||s->top==-1) return 0; return s->top+1;//栈的元素个数 } //返回一个栈顶元素,但是不出栈 int GetTop(SeqStack* s,SElemtype* e) { if(s==NULL||s->top==-1) return 0;//栈为空 *e=s->data[s->top]; return 1;//栈不为空 } /* @doubleInitStack:初始化一个共享栈 @maxl:栈的最大空间 @rerurn:返回一个栈的指针 */ doubleSeqStack* doubleInitStack(int maxl) { doubleSeqStack * stack=malloc(sizeof(doubleSeqStack)); stack->maxlen=maxl; stack->data=malloc(maxl*sizeof(SElemtype)); stack->top1=-1;//第一个栈空栈 stack->top2=maxl;//第二个栈空栈 return stack; } /* @doublePush:共享栈入栈 @doubleSeqStack* s:栈头 @SElemtype x:要入栈的元素 @stacknumber:哪个栈 */ int doublePush(doubleSeqStack* s,SElemtype x,int stacknumber) { if(s==NULL||s->top1+1==s->top2) { printf("栈溢出\n"); return 0;//入栈失败 } if(stacknumber==1)//往栈1添加元素 s->data[++s->top1]=x; if(stacknumber==2)//往栈2添加元素 s->data[--s->top2]=x; return 1;//入栈成功 } /* @doublePop:共享栈出栈 @doubleSeqStack* s:栈头 @SElemtype* e:要出栈的元素地址 @stacknumber:哪个栈 */ int doublePop(doubleSeqStack* s,SElemtype *e,int stacknumber) { if(s==NULL) { return 0;//出栈失败 } if(stacknumber==1) { if(s->top1==-1) { return 0; } *e=s->data[s->top1--]; } else { if(s->top2==s->maxlen) { return 0; } *e=s->data[s->top2++]; } return 1; }
链式栈
//数据节点: typedef int SElemType; //数据结点 typedef struct SNode { SElemType data ; //保存栈中的一个元素 struct SNode* next; struct SNode* prev; }SNode; //头节点 typedef struct LinkedStack { //栈顶 指向链式栈的最后一个元素 SNode * top; //栈底元素 SNode * first; //栈中的元素个数 int Nodenum; }LinkedStack;#include<stdio.h> #include<stdlib.h> #include"liststack.h" //@InitStack 初始化一个链式栈 //@return 返回一个链式栈的栈头 listStack* InitStack(void) { listStack* lstack=(listStack*)malloc(sizeof(listStack)); lstack->top=NULL; lstack->nodenum=0; lstack->first=NULL; return lstack; } //@Push:入栈 //@listStack* ls:栈的头节点 //@SElemtype x:入栈的元素 int Push(listStack* ls,SElemtype x) { if(ls==NULL) return 0;//失败 ls->nodenum+=1; SNode* p=malloc(sizeof(SNode)); p->data=x; p->next=NULL; p->prev=NULL; if(ls->top==NULL) { ls->top=p; ls->first=p; } else { ls->top->next=p; p->prev=ls->top; ls->top=p; } return 1;//入栈成功 } /* @Pop:出栈 @SeqStack* s:栈头 @SElemtype* e:要出栈的元素地址 */ int Pop(listStack* ls,SElemtype *e) { if(ls==NULL||ls->nodenum==0) { return 0;//出栈失败 } *e=ls->top->data; ls->nodenum-=1; SNode* px=ls->top; if(ls->nodenum==0) { ls->first=NULL; ls->top=NULL; free(px); } else { ls->top=px->prev; px->prev->next=NULL; free(px); } return 1; } //返回一个栈顶元素,但是不出栈 int gettop(listStack* ls,SElemtype* e) { if(ls==NULL||ls->nodenum==0) return 0;//栈为空 *e=ls->top->data; return 1;//栈不为空 } //@destroyliststack 销毁一个链式栈 void destoryliststack(listStack* ls) { if(ls==NULL) return; clearliststack(ls); free(ls); } //@Clearliststack 清空一个链式栈 void clearliststack(listStack* ls) { if(ls==NULL||ls->top==NULL) return; SNode* px=ls->first; while (px!=NULL) { ls->first=px->next; if(px->next!=NULL) { px->next->prev=NULL; } px->next=NULL; free(px); px=ls->first; } ls->top=NULL; ls->nodenum=0; } //判断一个栈是否为空 int liststackempty(listStack* ls) { if(ls==NULL||ls->nodenum==0) return 0;//栈为空 else return 1;//栈不为空 } //返回一个栈的元素个数 int liststacklength(listStack* ls) { if(ls==NULL||ls->nodenum==0) return 0; return ls->nodenum;//栈的元素个数 }
两栈的共享空间
栈的一个应用
后缀表达式
后缀表达式所有的运算符在操作数的后面!!中缀表达式
中缀表达式的运算符散布在操作其中!!![]()
作业
1、求一个表达式的值,表达式是以字符串的形式给出 表达式:整数的 +-/ “5+304+7/3”
int expression(char *e) { //你得先初始化两个栈 //操作数 d //运算符 s while(*e) { //先解析一个操作数 //直接就入栈 while(1) { //再解析一个运算符,待入栈的运算符 if(待入栈的运算符 比 栈顶的运算符 高) { //直接入栈s break; } else { //把运算符栈 栈顶元素 pop //把操作数栈 栈顶的元素 pop 两次 // a+b //再把结果入操作数的栈 } } } while(运算符栈不为空) { //把运算符栈 栈顶元素 pop //把操作数栈 栈顶元素 pop 两次 // a+b //再把结果入操作数的栈 } //最后的结果保存在操作数的栈中!! GOOD LUCK FOR YOU !!!! } int is_hiht(char ch1 , char ch2) { if((ch1 == '*' || ch1 == '/' || ch1 == '%')&& (ch2 == '+' ||ch2 == '-')) { return 1; } return 0; }
嵌入式学习一阶段——C语言:数据结构(3)
于 2023-09-08 16:19:43 首次发布