数据结构——链式栈模板类实现

向右看齐 2022-06-07 07:08 332阅读 0赞

数据结构笔记3.1.3
链式栈和前面的顺序栈是栈的两种不同实现形式,其实就是顺序表与链式表,区别在于其实现的方式(数组和指针节点),顺序栈指的是其每个节点的物理存储是连续的,因为是使用数组实现的。而链式栈存储位置则是不连续的,需要指针来穿接。
但是因为栈的操作单调,相对于单链表更容易实现,单链表相当于是一个泛泛的存储表,其操作更加任意,而像栈、队列这种数据组织结构,其只能在整个表的端进行操作,这也从另一个方面体现出链式栈相对容易实现。
那为何有顺序表这种总领性的结构,还要建立栈、队列这些子数据结构呢?这就好比是“专门化”与“普遍化”的比较,一般专门化的东西,其在相应问题上的效率会比普遍使用的工具要高,所以,分化后的子结构其存在的意义绝不容小视!最后说一下顺序栈与链式栈的比较,他们都是一种数据组织与操纵方式(DRO),但是在解决不同问题的时候,不同的存储方式实现同样的功能,可能在效率、复杂度、空间利用率等方面都会千差万别,各有千秋!下面贴出代码:
模板类——链式栈

  1. //数据结构——链式栈的模板类定义 By Zhu Xiuyu 17/10/13
  2. #include <iostream>
  3. #include <cassert>
  4. using namespace std;
  5. //节点定义
  6. template<class T>
  7. struct StackNode {
  8. T data; //栈每个节点的数据域
  9. StackNode<T> *next; //栈节点的指针域
  10. StackNode(T x, StackNode<T> *Node = NULL) : data(x){}
  11. };
  12. //模板类定义
  13. template<class T>
  14. class LinkedStack {
  15. public:
  16. LinkedStack() : top(NULL){} //构造函数
  17. ~LinkedStack(); //析构函数
  18. void Push(const T & x); //进栈
  19. bool Pop(T & x); //出栈
  20. bool getTop(T & x) const; //读取栈顶元素
  21. bool isEmpty()const; //判断栈是否为NULL
  22. int getSize() const; //求栈的元素的个数
  23. void makeEmpty(); //清空栈
  24. void output(ostream & out); //输出函数(此处由重载函数调用)
  25. private:
  26. StackNode<T> *top; //栈顶指针
  27. };
  28. //函数定义
  29. template<class T>
  30. void LinkedStack<T>::makeEmpty() {
  31. //逐个删去链式栈中的元素,直至栈顶指针为空
  32. StackNode<T> *p; //逐个节点释放
  33. while (top != NULL) {
  34. p = top;
  35. top = top->next;
  36. delete p;
  37. }
  38. }
  39. template<class T>
  40. LinkedStack<T>::~LinkedStack() {
  41. //析构函数
  42. makeEmpty();
  43. }
  44. template<class T>
  45. bool LinkedStack<T>::isEmpty() const{
  46. if (NULL == top) {
  47. return true;
  48. }
  49. return false;
  50. }
  51. template<class T>
  52. void LinkedStack<T>::Push(const T & x) {
  53. //将元素x推入栈顶
  54. StackNode<T> *newNode = new StackNode<T>(x);
  55. assert(newNode != NULL); //内存分配错误的中断处理
  56. newNode->next = top;
  57. top = newNode;
  58. }
  59. template<class T>
  60. bool LinkedStack<T>::Pop(T & x) {
  61. //删除栈顶节点,删除的data返回到x当中
  62. if (isEmpty()) {
  63. return false; //栈为NULL出栈失败
  64. }
  65. StackNode<T> *p = top; //标记Top
  66. top = top->next; //更新栈顶指针
  67. x = p->data;
  68. delete p; //释放栈顶元素
  69. return true;
  70. }
  71. template<class T>
  72. bool LinkedStack<T>::getTop(T & x) const {
  73. //返回栈顶元素的值
  74. if (isEmpty()) {
  75. return false; //栈为NULL,读取栈顶失败
  76. }
  77. x = top->data;
  78. return true;
  79. }
  80. template<class T>
  81. int LinkedStack<T>::getSize()const {
  82. StackNode<T> *p = top;
  83. int len = 0;
  84. while (p != NULL) {
  85. p = p->next;
  86. len++;
  87. }
  88. return len;
  89. }
  90. template<class T>
  91. void LinkedStack<T>::output(ostream & out) {
  92. //输出链式栈
  93. StackNode<T> *p = top;
  94. while (p != NULL) {
  95. out << p->data << ' ';
  96. p = p->next;
  97. }
  98. }
  99. template<class T>
  100. ostream & operator << (ostream & out, LinkedStack<T> & LS) {
  101. //重载输出运算符
  102. LS.output(out); //避免友元函数在模板class中出现的问题
  103. cout << endl;
  104. return out;
  105. }

测试Main函数

  1. int main()
  2. {
  3. //Push and Pop测试
  4. LinkedStack<int> LS; //定义一个链式栈
  5. LS.Push(1);
  6. LS.Push(2);
  7. LS.Push(3);
  8. LS.Push(4);
  9. LS.Push(5);
  10. cout << LS; //用重载函数输出
  11. int del1, del2;
  12. LS.Pop(del1);
  13. LS.Pop(del2);
  14. cout << LS;
  15. //getSize 和 getTop测试
  16. int topVal = 0;
  17. LS.getTop(topVal);
  18. cout << topVal << endl;
  19. cout << LS.getSize() << endl;
  20. //判断是否为NULL测试
  21. if (LS.isEmpty()) {
  22. cout << "空栈" << endl;
  23. }
  24. else {
  25. cout << "非空栈" << endl;
  26. }
  27. LS.makeEmpty();
  28. if (LS.isEmpty()) {
  29. cout << "空栈" << endl;
  30. }
  31. else {
  32. cout << "非空栈" << endl;
  33. }
  34. system("pause");
  35. return 0;
  36. }

运行效果:
这里写图片描述

发表评论

表情:
评论列表 (有 0 条评论,332人围观)

还没有评论,来说两句吧...

相关阅读