xhao 2020-05-04
栈
定义:栈是一个先进后出的线性表,要求只在表尾进行删除和插入操作
注:对于栈来说,表尾成为栈的栈顶(top),相应的表头称为栈低(bottom)。
因为栈的本质是线性表,所以栈也分为顺序存储结构和链式存储结构;(一般用顺序存储实现)
栈的顺序存储:
#include <stdio.h> #include <malloc.h> #include <stdlib.h> #define initSize 10 #define sup 2 typedef int ElemType; typedef struct{ int stackSize;//栈当前可用最大容量 ElemType *base;//栈低 ElemType *top;//栈顶 }sqStack; void initStack(sqStack *); void Push(sqStack *,ElemType); void pop(sqStack *,ElemType *); void pop(sqStack *s,ElemType *val){ if(s->base==s->top){ return ; } *val=*(--s->top); } void Push(sqStack *s,ElemType val){ if(s->top-s->base>=s->stackSize){//判断栈是否存满,并追加空间 s->base=(ElemType *)realloc(s->base,(s->stackSize+sup) * sizeof(ElemType)); if(!s->base) exit(0); s->top=s->base+s->stackSize; s->stackSize+=sup; } *(s->top)=val;//栈顶压栈数据 s->top++; } void initStack(sqStack *s){ s->base=(ElemType *)malloc(initSize * sizeof(ElemType)); if(!s->base) exit(0); s->top=s->base; s->stackSize=initSize; } void main(){ int val; sqStack s; initStack(&s); printf("请输入压栈(-1退出):"); scanf("%d",&val); while(val != -1){ Push(&s,val); printf("请输入压栈(-1退出):"); scanf("%d",&val); } printf("开始弹栈:\n"); while(s.top!=s.base){ pop(&s,&val); printf("%d ",val); } }
后缀表达式
利用栈的方式:遍历中缀表达式;为数字压栈,为符号时弹栈;
方法:从左到右遍历中缀表达式,若为数字时直接输出;若为符号,则判断其与栈顶符号的优先级:是‘)’的话则栈中符号依次出栈,直到遇到‘(’【括号不会输出在后缀表达式中】;其他符号:如果该符号优先级小于等于栈顶优先级,则栈中符号依次弹栈输出,直到栈顶符号优先级小于带压栈符号优先级或者栈顶为‘(’;如果遍历结束,再将栈中符号依次出栈输出;
例如:5+2*(3*(3-1*2+1)) => 523312*-1+**+
后缀表达式的计算:1、按次序读取后缀表达式的每个字符。2、读取到操作数时,把操作数压入栈中。3、读取到操作符时,对栈顶的2个操作数做相应运算,要注意操作数的前后顺序。结果压入栈中。4、读取完所有字符后,弹出栈。得到的值就是所求结果。
队列
定义:只允许在一端进行插入操作,另一端进行删除操作的线性表
与栈相反,队列是一种先进后出的线性表。
队列既可以用链表实现,也可以用顺序存储实现,(一般用链表实现)
#include <stdio.h> #include <malloc.h> #include <stdlib.h> typedef int ElemType; typedef struct QNode{ ElemType data; struct QNode *next; }QNode,* QueuePrt; typedef struct{ QueuePrt head;//队头 QueuePrt rear;//队尾 }LinkQueue; void init(LinkQueue *); void Insedt(LinkQueue *,ElemType); void pop(LinkQueue *,ElemType *); void init(LinkQueue *q){ q->head=q->rear=(QueuePrt)malloc(sizeof(QNode)); if(!q->head) exit(0); q->head->next=NULL; } void Insedt(LinkQueue *q,ElemType e){ QueuePrt p=(QueuePrt)malloc(sizeof(QNode)); if(p==NULL) exit(0); p->data=e; p->next=NULL; q->rear->next=p;//用队尾链接 q->rear=p;//更新队尾 } void pop(LinkQueue *q,ElemType *e){ QueuePrt p=q->head->next;//得到队列中头结点指向的结点()队列中第一个值 q->head->next=p->next;//更新头结点指向的结点(在队列中删除原先第一个有值结点) if(q->rear==p){//判断删除结点是否为队列中最后一个结点 q->rear=q->head;//队列将要成为空队列,将指向尾结点的指针指向头结点 } *e=p->data; free(p); } void main(){ ElemType val; LinkQueue s; init(&s); printf("%d\n",s.head->data); printf("请输入进入队列的数(-1退出):"); scanf("%d",&val); while(val != -1){ Insedt(&s,val); printf("请输入进入队列的数(-1退出):"); scanf("%d",&val); } printf("开始出队列:\n"); while(s.head!=s.rear){ pop(&s,&val); printf("%d ",val); } printf("\n"); }