数据结构与算法分析 - 2 - 栈ADT
Posted cofjus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法分析 - 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
以上是关于数据结构与算法分析 - 2 - 栈ADT的主要内容,如果未能解决你的问题,请参考以下文章