[关闭]
@okokme 2019-01-08T10:30:03.000000Z 字数 3220 阅读 397

数据结构


应用:如使用浏览器上网时,不管什么浏览器都有一个"后退"键,你点击后可以按访问顺序的逆序加载浏览过的网页.
<撤销>这种操作就是使用栈来实现的.

栈(stack)是限定仅在表尾进行插入和删除的线性表.

我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈.栈又称为先进后出的线性表.简称LIFO结构.

注:栈就是一个有特殊约束的线性表.

最先进栈的元素就一定最后出栈吗?
不一定,要看什么情况.栈对线性表的插入,删除的位置都进行了限制,并没有对元素的进出时间进行限制,也就是说,在不是所有元素都近栈的情况下,实现进去的元素也可以出栈,只要保证是栈顶元素出栈就可以.
如: 1,2,3依次进栈
① 1,2,3进,再3,2,1出. 出栈顺序为321
② 1进,1出,2进,2出,3进,3出. 出栈顺序为123
③ 1进,2进,2出,1出,3进,3出.出栈次序为213
④ 1进,1出,2进,3进,3出,2出. 出栈次序为132
⑤ 1进,2进,2出,1出,3进,3出. 出栈次序为231

栈的抽象数据模型

插入和删除操作操作会有变化改名为push pop

  1. ADT 栈(stack)
  2. Data
  3. 同线性表.元素具有相同的类型,相邻元素具有前驱和后继的关系
  4. Operation
  5. InitStack(*S);初始化操作,建立一个空栈S
  6. DestoryStack(*S);若栈存在,则销毁他
  7. ClearStack(*S);将栈清空
  8. StackEmpty(S);若栈为空,返回true,否则返回faluse
  9. GetTop(S*e);若栈存在非空,用e返回S的栈顶元素
  10. Push(*S,e);若栈存在,插入新元素e到栈S中并成为栈顶元素
  11. Pop(*S,e);删除S中的栈顶元素,并用e返回其值.
  12. StackLength(S);返回栈S的元素个数
  13. endADT

栈的结构定义

  1. typedef int SElemType;/*假定int类型*/
  2. typedef struct
  3. {
  4. SElemType data[MAXSIZE];
  5. int top;/*用于栈顶指针*/
  6. }SeqStack;

顺序栈的基本操作:

①初始化

  1. void InitStack(SeqStack *s)
  2. {
  3. S->top = -1;
  4. }

②判栈空

  1. int IsEmpty(SeqStack *S)
  2. {
  3. return(S->top==-1? TURE :FALSE);
  4. }

③判栈满

  1. int IsFull(SeqStack *S)
  2. {
  3. return(S->top==MAXSIZE-1?TRUE:FALSE);
  4. }

④进栈

  1. int Push(SeqStack *S, SElemType x)
  2. {
  3. if(S->top == MAXSIZE-1)/*栈满*/
  4. return FALSE;
  5. S->top++;
  6. S->data[S->top] = e;
  7. return TRUE;
  8. }

⑤出栈

  1. int pop(SeqStack *S, SElemType*x)
  2. {
  3. if(S->top == -1)
  4. return FALSE;
  5. *x = S->data[S->top];
  6. S->top--;
  7. return TRUE;
  8. }

⑥取栈顶

  1. int GetTop(SeqStack *S,SElemtype*x)
  2. {
  3. if(S->top == -1)
  4. return FALSE;
  5. *x = S->data[S->top];
  6. return TRUE;
  7. }

注:进栈出栈取栈顶的代码时间复杂度为O(1)

缺陷:必须事先确定数组存储空间的大小

如果我们有两个相同的类型的栈,我们为他们重新开辟了数组空间,极有可能是第一个栈已经满了,再进栈就溢出了,而另一个栈还有很多存储空间,我们完全可以使用一个数组来存储两个栈,只不过我们得使用点小技巧.

双端栈

空间有限的情况下充分利用
两栈共享技术---双端栈

主要利用了栈"栈底位置不变,栈顶位置动态变化"的特性
首先为两个栈申请一个共享的一维数组空间S[M],将两个栈的栈底分别放在一位数组的两端,分别是0,M-1

两栈共享数据结构定义

  1. #define M 100
  2. typedef struct
  3. {
  4. SElemType data[M];
  5. SElemType top[2];/*与上不同的是top指针现在有两个*/
  6. }DqStack;

使用top[0]和top[1]来表示两栈栈顶
注意:1.操作需要表明具体栈(top[0]还是top[1])
2.栈空判断: 栈S1: top[0]=-1;
栈S2: top[1]=M;
3.栈满判断: 当两个栈迎面相迎时才会溢出,即top[0]+1=top[1]

①初始化

  1. void InitStack(DqStack *S)
  2. {
  3. S->top[0]=-1;
  4. S->top[1]=M;
  5. }

②进栈

  1. int Push(Dqstack *S, StackElemType x, int i)
  2. {
  3. if(S->top[0]+1 == S->top[1])/*栈满*/
  4. return FALSE;
  5. switch(i)
  6. {
  7. case 0: S->top[0]++;
  8. S->data[S->top[0]]=x;
  9. break;
  10. case 1: S->top[1]++;
  11. S->data[S->top[1]]=x;
  12. break;
  13. default: return FALSE;
  14. }
  15. return TRUE;
  16. }

栈的链式存储

注意入栈与出栈要检查站是否为空(是否为满)

入栈检查 是否栈满:

  1. if(s = (slStacktype *)malloc(sizeof(slStacktype)) == NULL)
  2. return FALSE;

出栈检查 是否栈空:

  1. if(top->next == NULL)
  2. return FALSE;

链栈的c语言定义为:

  1. typedef ELemtype int; //初始数据类型
  2. typedef struct Stacknode
  3. {
  4. Elemtype data;
  5. struct Stacknode *next;
  6. }slStacktype;

入栈操作:

  1. int pushLstack(slStacktype *top, Elemtype x)
  2. {/*将元素s压入链栈top之中*/
  3. slStacktype *p;
  4. if(p = (slStacktype *)malloc(sizeof(slStacktype)) == NULL)
  5. return FALSE;
  6. p->data = x;
  7. p->next = top->next;
  8. top->next = p;
  9. return TRUE;
  10. }

出栈操作:

  1. Elemtype popLstack(slStacktype *top)
  2. {/*从链栈top中删除栈顶元素*/
  3. slStacktype *p;
  4. Elemtype x;
  5. p = top->next;
  6. top->next = p->next;
  7. p->data = x;
  8. free(p);
  9. return x;
  10. }

多个链栈的操作

我们可以将多个链栈的栈顶指针放在一个一维数组中统一管理

  1. slStacktype *top[M];

其中,top[0],top[1],...,top[M-1]指向M个不同的链栈,分别是M个链栈的栈顶指针,操作时只需确定链栈号i,然后以top[i]为栈顶指针进行栈操作,就可以实现各种操作.
①入栈操作

  1. int pushDupLs(slStacktype *top[M], int i, Elemtype x)
  2. {/*将元素x压入链栈top[i]中*/
  3. slStacktype *p;
  4. if( (p = (slStacktype*)malloc(sizeof(slStacktype))) == NULL)
  5. return FALSE;
  6. /*申请一个节点*/
  7. p->data = x;
  8. p->next = top[i]->next;
  9. top[i]->next = p;
  10. return TRUE;
  11. }

②出栈操作

  1. Elemtype popDupLs(slStacktype *top[M], int i)
  2. {/*从链栈top[i]中删除栈顶元素*/
  3. slStacktype *p;
  4. Elemtype x;
  5. if(top[i]->next == NULL)/*空栈*/
  6. return NULL;
  7. p = top[i]->next;
  8. top[i]->next = p->next;
  9. x = p->data;
  10. free(p);
  11. return x;
  12. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注