数据结构与算法分析 - 2 - 栈ADT

1.描述:实质是一种受到限制的表,即插入删除只能在表的末端,能够实现LIFO(后进先出)

2.栈的实现

  链表实现(链栈)

  数组实现(顺序栈)

3.链栈

创建一个空栈

 1 struct Node 
 2 {
 3     int value;
 4     Node *next;
 5 };
 6 
 7 //创建了一个头节点为S的链栈,S将一直表示栈顶元素
 8 Node *CreatStack()
 9 {
10     Node *S = new Node;
11     S->next = NULL;
12     return S;
13 }

测试栈是否为空

1 int IsEmpty(Node *S)
2 {
3     return S->next == NULL;
4 }

从栈顶弹出元素

 1 void Pop(Node *S)
 2 {
 3     Node *FirstCell;
 4     if (IsEmpty(S))                  //空栈,将返回异常
 5         cout << "Empty Stack" << endl;
 6     else
 7     {
 8         FirstCell = S->next;            //取出栈顶
 9         S->next = S->next->next;          //使S指向新的栈顶
10         delete FirstCell;              //删除原栈顶,完成出栈
11     }
12 }

返回栈顶元素(不弹出,不改变栈顶指针),遇到空栈将返回异常

1 int Top(Node *S)
2 {
3     if (!IsEmpty(S))
4         return S->next->value;
5 }

清空栈(同时销毁物理内存)

1 void MakeEmpty(Node *S)
2 {
3     while (!IsEmpty(S))
4         Pop(S);
5 }

压栈

 1 void Push(int x, Node *S)
 2 {
 3     Node *TempCell = new Node;
 4     if (TempCell == NULL)
 5         cout << "Out of space" << endl;
 6     else
 7     {
 8         TempCell->value = x;          //把x赋值给value
 9         TempCell->next = S->next;        //将新节点设为栈顶
10         S->next = TempCell;           //使S指向新的栈顶
11     }
12 }

遍历栈

1 void Print(Node *S)
2 {
3     Node *p = S->next;        //将p初始化为栈顶
4     while (p != NULL)
5     {
6         cout << p->value << endl;
7         p = p->next;
8     }
9 }

注意,内存分配操作的时间开销较大(C的malloc和free,C++的new和delete),可用通过建立第二个栈来避免,第一个栈中的元素弹出时将不会被删除,而是暂时存放在第二个栈中,然后当第一个栈需要新的元素时,将首先在第二个栈中查找,由于在链栈中,所有的操作均花费常数时间,所以检索第二个栈的开销相对于内存分配是值得的。

声明一个Stack链表

1 struct Stack 
2 {
3     Node *top;        //top指向栈顶
4     Node *bottom;      //bottom指向栈底
5 };

这样在任意Node处都可以通过p->top或者p->bottom的方式获得当前栈的栈顶和栈底

判断栈是否为空也可以这样进行 

1 int IsEmpty(Node *p)
2 {
3     if (p->top == p->bottom)     //栈顶和栈底相同
4         return 1;
5     else
6         return 0;
7 }

4.顺序栈

数组实现的顺序栈避免了使用指针,顺序栈使用一个一维数组来存放栈的元素

每一个栈有一个TopOfStack,对于空栈来说TopOfStack = -1

压栈时,将TopOfStack加1,Stack[TopOfStack] = x;出栈时,减1

1 typedef struct StackRecord 
2 {
3     int capacity;    //栈大小
4     int TopOfStack;     //栈顶
5     int *Array;         //数组地址
6 }Stack;

对空栈的pop和满栈的push都将引起程序崩溃

创建栈,数组实现

 创建空栈

1 void MakeEmpty(Stack *S)
2 {
3     S->TopOfStack = -1;
4 }

创建栈(不考虑内存申请失败)

1 Stack* CreatStack(int MaxSize)
2 {
3     StackRecord *S = new StackRecord;
4     S->Array = new int[MaxSize];
5     S->capacity = MaxSize;
6     MakeEmpty(S);
7     return S;
8 }

 检测是否为空栈

1 int IsEmpty(Stack *S)
2 {
3     return S->TopOfStack == -1;
4 }

检测是否为满栈

1 int IsFull(Stack *S)
2 {
3     return S->TopOfStack == MaxSize - 1;
4 }

进栈

1 void Push(int x, Stack *S)
2 {
3     if (IsFull(S))              //栈满将抛出异常
4         ;
5     else
6         S->Array[++S->TopOfStack] = x;
7   //S->TopOfStack++;
8 //S->Array[
TopOfStack] = x;
9 }

返回栈顶元素

1 int Top(Stack *S)
2 {
3     if (!IsEmpty(S))
4         return S->Array[S->TopOfStack];
5     else
6         ;
7 }

出栈

1 void Pop(Stack *S)
2 {
3     if (IsEmpty(S))
4         ;
5     else
6         S->TopOfStack--;
7 }

栈的遍历

以遍历数组的方式遍历即可

释放栈

1 void DisposeStack(Stack *S)
2 {
3     if (S != NULL)
4     {
5         delete S->Array;
6         delete S;
7     }
8 }

5.链栈与顺序栈

顺序栈比链栈操作简便,避免了指针,但对存储空间利用效率低,大小固定,不如链表实现灵活

数组实现时,声明的栈太小,会造成栈溢出,太大则造成空间浪费

6.栈的应用

挖坑待填

参考资料:《数据结构与算法分析——C语言描述》    Mark Allen Weiss 

猜你喜欢

转载自www.cnblogs.com/CofJus/p/10202451.html
今日推荐