数据结构(寒假小结)--3.1桟
来源:互联网 发布:手机贴膜品牌 知乎 编辑:程序博客网 时间:2024/06/18 10:35
1.本节学习要点:![](http://img.blog.csdn.net/20160128163619975)
2.基本定义及相关名词:
栈(Stack):限制在表的一端进行插入和删除运算的线性表。
空栈:当表中没有元素时。
栈顶(Top):插入、删除的一端;栈底(Bottom):另一端。
栈为后进先出(Last In First Out)的线性表,简称为LIFO表。
- 上溢:当栈满时再进栈必定产生空间溢出,简称“上溢”;上溢是一种出错状态,应该设法避免;
- 下溢:当栈空时再退栈也将产生溢出,简称“下溢”;下溢则可能是正常现象,因为栈初态或终态都是空,下溢常作程序控制转移的条件。
3.桟的基本运算:
- 初始化INITIATE(S):构造一个空栈S。
- 判栈空EMPTY(S):若栈S空,返回1,否则返回0。
- 进栈PUSH(S, x):在栈顶插入(压入)元素x,x 成为新的栈顶。
- 退栈POP(S):将栈顶元素删除(弹出),并返回该元素。
- 取栈顶GETTOP(S):取栈顶元素,但不删除它。
4.顺序桟
顺序栈:栈的顺序存储结构,运算受限的顺序表
用数组来实现
栈底位置不变,可设在数组两端的任何一端;
- 栈顶位置随进栈、退栈而变,需用一个整型变量top指示 当前位置,通常称top为栈顶指针。
- 栈空:top=-1;栈满:top=maxsize-1;
顺序桟的基本运算:
typedef int datatype; //栈元素类型,假设为整型const int maxsize=100; //栈容量typedef struct { datatype data[maxsize]; int top;} sqstack;//顺序栈类型//初始化void init_sqstack(sqstack *sq) { sq–>top=-1;}//判空int empty_sqstack(sqstack *sq) { if(sq−>top==−1) return 1; else return 0;}//进桟int push_sqstack(sqstack *sq,datatype x) { if(sq−>top==maxsize−1) {cout<<"栈满,不能进栈!\n"; return 0;} //上溢 else {sq−>data[++sq−>top]=x; return 1;}}//退桟int pop_sqstack(sqstack *sq,datatype *x) { if(sq−>top==−1) {cout<<"栈空,不能退栈!\n"; return 0;}//下溢 else {*x=sq−>data[sq−>top−−]; return 1;}}//取桟顶int gettop_sqstack(sqstack *sq,datatype *x) { if(sq−>top==−1) {cout<<"栈空,无栈顶可取!\n"; return 0;} else {*x=sq−>data[sq−>top]; return 1;}}
5.链表
链栈:栈的链式存储结构,运算受限的单链表。
链桟的基本运算:
typedef struct node * pointer; struct node { datatype data; pointer next;}; //链栈结点类型typedef struct { pointer top;} lkstack;//链栈类型//初始化void init_lkstack(lkstack *ls) { ls−>top=NULL;}//判空int empty_lkstack(lkstack *ls) { if(ls−>top==NULL) return 1; else return 0;}//进桟void push_lkstack(lkstack *ls,datatype x) { pointer p; p=new node; //申请新结点*p p−>data=x; //新结点data域装入x的值 p−>next=ls−>top; //新结点next为原栈顶 ls−>top=p; //新结点为新栈顶}//退桟int pop_lkstack(lkstack *ls,datatype *x) { pointer p; if(ls−>top==NULL) {cout<<”栈空,不能退栈!\n”; return 0;}//下溢 else {p=ls−>top; *x=p−>data; ls−>top=p−>next; delete p; return 1;}}//取桟顶int gettop_lkstack(lkstack *ls,datatype *x) { if(ls−>top==NULL) {cout<<”栈空,无栈顶可取!\n”;return 0;}//栈空 else {*x=ls−>top−>data; return 1;}}
6.顺序桟与链桟的比较
时间性能:相同,都是常数时间O(1)。
空间性能:
顺序栈:有元素个数的限制和空间浪费的问题。
链栈:没有栈满的问题,只有当内存没有可用空间时才会出现栈满,但是每个元素都需要一个指针域,从而产生了结构性开销。
PS:栈的使用过程中元素个数变化较大时,用链栈是适宜的,反之,应该采用顺序栈
7.桟的应用
1.递归
#include<stdio.h>long f(int 3){ if(n==0) return 1; else return n*f(n−1);}void main(){ //求f(3); printf("f(3)=",f(3));}
2.表达式求值
(迂者-贺利坚老师写得挺好,偷懒)
#include <stdio.h>#include <stdlib.h>#define MaxOp 100#define MaxSize 100struct //设定运算符优先级{ char ch; //运算符 int pri; //优先级}lpri[]= {{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},//左运算符op的优先级rpri[]= {{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};//右运算符op的优先级int leftpri(char op) //求左运算符op的优先级{ int i; for (i=0; i<MaxOp; i++) if (lpri[i].ch==op) return lpri[i].pri;}int rightpri(char op) //求右运算符op的优先级{ int i; for (i=0; i<MaxOp; i++) if (rpri[i].ch==op) return rpri[i].pri;}bool InOp(char ch) //判断ch是否为运算符{ if (ch=='(' || ch==')' || ch=='+' || ch=='-' || ch=='*' || ch=='/') return true; else return false;}int Precede(char op1,char op2) //op1和op2运算符优先级的比较结果{ if (leftpri(op1)==rightpri(op2)) return 0; else if (leftpri(op1)<rightpri(op2)) return -1; else return 1;}void trans(char *exp,char postexp[])//将算术表达式exp转换成后缀表达式postexp{ struct { char data[MaxSize]; //存放运算符 int top; //栈指针 } op; //定义运算符栈 int i=0; //i作为postexp的下标 op.top=-1; op.top++; //将'='进栈 op.data[op.top]='='; while (*exp!='\0') //exp表达式未扫描完时循环 { if (!InOp(*exp)) //为数字字符的情况 { while (*exp>='0' && *exp<='9') //判定为数字 { postexp[i++]=*exp; exp++; } postexp[i++]='#'; //用#标识一个数值串结束 } else //为运算符的情况 switch(Precede(op.data[op.top],*exp)) { case -1: //栈顶运算符的优先级低:进栈 op.top++; op.data[op.top]=*exp; exp++; //继续扫描其他字符 break; case 0: //只有括号满足这种情况 op.top--; //将(退栈 exp++; //继续扫描其他字符 break; case 1: //退栈并输出到postexp中 postexp[i++]=op.data[op.top]; op.top--; break; } } //while (*exp!='\0') while (op.data[op.top]!='=') //此时exp扫描完毕,退栈到'='为止 { postexp[i++]=op.data[op.top]; op.top--; } postexp[i]='\0'; //给postexp表达式添加结束标识}float compvalue(char exp[]) //计算后缀表达式的值{ struct { float data[MaxSize]; //存放数值 int top; //栈指针 } st; //定义数值栈 float d; char ch; int t=0; //t作为exp的下标 st.top=-1; ch=exp[t]; t++; while (ch!='\0') //exp字符串未扫描完时循环 { switch (ch) { case'+': st.data[st.top-1]=st.data[st.top-1]+st.data[st.top]; st.top--; break; case '-': st.data[st.top-1]=st.data[st.top-1]-st.data[st.top]; st.top--; break; case '*': st.data[st.top-1]=st.data[st.top-1]*st.data[st.top]; st.top--; break; case '/': if (st.data[st.top]!=0) st.data[st.top-1]=st.data[st.top-1]/st.data[st.top]; else { printf("\n\t除零错误!\n"); exit(0); //异常退出 } st.top--; break; default: d=0; //将数字字符转换成数值存放到d中 while (ch>='0' && ch<='9') //为数字字符 { d=10*d+ch-'0'; ch=exp[t]; t++; } st.top++; st.data[st.top]=d; } ch=exp[t]; t++; } return st.data[st.top];}int main(){ char exp[]="(56-20)/(4+2)"; //可将exp改为键盘输入 char postexp[MaxSize]; trans(exp,postexp); printf("中缀表达式:%s\n",exp); printf("后缀表达式:%s\n",postexp); printf("表达式的值:%g\n",compvalue(postexp)); return 0;}
如果有错误请大家指出,共同学习共同进步!更多百度百科
1 0
- 数据结构(寒假小结)--3.1桟
- 数据结构(寒假小结)--3.3串
- 数据结构(寒假小结)——2.线性表
- 数据结构(寒假小结)——3.2队列
- 大二寒假小结(上)
- 大二寒假小结(中)
- 数据结构(寒假小结)——2.1线性表之顺序表
- 数据结构(寒假小结)——2.2线性表之单链表
- 数据结构(寒假小结)——2.3线性表之双链表和循环链表
- 寒假小结
- 寒假生活小结
- 2013年底寒假小结
- 寒假英语小结
- 寒假自学JAVA小结
- 2017寒假训练 小结
- 2017寒假小结
- 16年寒假学习小结
- 数据结构小结 (一)总论
- 前端学习的开始
- deepin 2014中chrome扩展安装与android apk运行
- Service (aidl远程服务)
- 关于禁用数据库访问方法
- Android中关于Activity/ActionBarActivity/AppCompatActivity的区分与理解
- 数据结构(寒假小结)--3.1桟
- 命令和快捷键小结
- 99. Recover Binary Search Tree
- 仿EasyTouch实现一键返回功能
- Oracle创建表空间及在指定的表空间上创建数据库的步骤
- UITableView中Cell重用机制导致内容重复解决方法
- C#中WinForm窗体的单例模式,避免窗体被实例化多次
- 使用fragment,editvView ,listView,出现软键盘遮挡
- Xcode配置OpenGL