栈和队列

来源:互联网 发布:天正看图软件 编辑:程序博客网 时间:2024/06/05 05:35

1.1 栈的定义

栈是一种特殊

的线性表。其特殊性在于限定插入和删除数据元素的操作只能在线性表的一端进行。如下所示:

结论:后进先出(Last In First Out),简称为LIFO线性表。

栈的基本运算有六种:

构造空栈:InitStack(S)、

判栈空: StackEmpty(S)、

判栈满: StackFull(S)、

进栈: Push(S,x)、可形象地理解为压入,这时栈中会多一个元素

退栈: Pop(S) 、 可形象地理解为弹出,弹出后栈中就无此元素了。

取栈顶元素:StackTop(S),不同与弹出,只是使用栈顶元素的值,该元素仍在栈顶不会改变。

    由于栈也是线性表,因此线性表的存储结构对栈也适用,通常栈有顺序栈链栈两种存储结构,这两种存储结构的不同,则使得实现栈的基本运算的算法也有所不同。

我们要了解的是,在顺序栈中有"上溢"和"下溢"的概念。顺序栈好比一个盒子,我们在里头放了一叠书,当我们要用书的话只能从第一本开始拿(你会把盒子翻过来吗?真聪明^^),那么当我们把书本放到这个栈中超过盒子的顶部时就放不下了(叠上去的不算,哼哼),这时就是"上溢","上溢"也就是栈顶指针指出栈的外面,显然是出错了。反之,当栈中已没有书时,我们再去拿,看看没书,把盒子拎起来看看盒底,还是没有,这就是"下溢"。"下溢"本身可以表示栈为空栈,因此可以用它来作为控制转移的条件。

链栈则没有上溢的限制,它就象是一条一头固定的链子,可以在活动的一头自由地增加链环(结点)而不会溢出,链栈不需要在头部附加头结点,因为栈都是在头部进行操作的,如果加了头结点,等于要在头结点之后的结点进行操作,反而使算法更复杂,所以只要有链表的头指针就可以了。


1.2 栈的顺序存储

使用c++的面向对象封装:

// Test.cpp : Defines the entry point for the console application.  //  #include "stdafx.h"    #include <iostream>  using namespace std;  #define MAX 10 // MAXIMUM STACK CONTENT  class stack     {     private:         int arr[MAX];       int top;   public:         stack()       {             inItStack();       }      /************************************************************************/      /* 初始化栈                                                                     */      /************************************************************************/      void inItStack()       {           top=-1;       }       /************************************************************************/      /* 入栈                                                                     */      /************************************************************************/      void push(int a)       {             top++;          if(top < MAX)  {                 arr[top]=a;           }   else   {                 cout<<"STACK FULL!!"<<top;             }         }         /************************************************************************/      /* 出栈                                                                     */      /************************************************************************/      int pop()      {              if(isEmpty())   {                 cout<<"STACK IS EMPTY ";              return NULL;             } else {                 int data=arr[top];               arr[top]=NULL;               top--;              return data;           }         }           /************************************************************************/      /* 是否为空                                                                     */      /************************************************************************/      bool isEmpty()      {          if(top == -1) return true;          else return false;      }  };     int main()     {         stack a;         a.push(3);         a.push(10);         a.push(1);         cout<<"Pop:"<<a.pop();            return 0;     }  
结论:由于栈的插入和删除操作具有它的特殊性,所以用顺序存储结构表示的栈并不存在插入删除数据元素时需要移动的问题,但栈容量难以扩充的弱点仍就没有摆脱。

1.3 栈的链式存储
若是栈中元素的数目变化范围较大或不清楚栈元素的数目,就应该考虑使用链式存储结构。人们将用链式存储结构表示的栈称作"链栈"。链栈通常用一个无头结点的单链表表示。如图所示:



0 0