源程序:
// 3_a2.cpp —— 链式栈的定义 /* * -> 程序要求: * 1. 完成对链栈结构的定义,以及对链栈的各种基本运算的实现(每种基本运算用一个函数来实现)。 * 2. 基本运算包括:初始化Init_lkstack运算、判栈空Empty_lkstack运算、入栈Push_lkstack运算、出栈Pop_lkstack运算、取栈顶元素Gettop_lkstack运算。 * 3. 并且在main函数中分别调用以上各种基本运算的函数来使用,以验证其功能已实现。 * 4. 此题的源程序保存为 3_a2.cpp。 **/ /* * -> 程序分析 * 1. 创建一个栈,一般依照以下几个步骤: * 2. 如果从创建栈所要实现的功能顺序去考虑的话,可以分为以下几步:[初始化,入栈,取元素,计长度,出栈,销毁] * 3. 再从上面几个步骤深入去想,可能还需要有几个函数:[判空,判满] * 4. 之后从类去想的话,类的成员函数已确定,还差几个数据成员:[栈的长度,指针结点(top),存放数据的变量] **/ #include <iostream> #include <cstdlib> using std::cin; using std::cout; using std::endl; ////////////////////////////////////// 链式栈的结点类 ///////////////////////////////////////// template <typename elem> class stack; // 类的提前声明 template <typename elem> class stacknode { friend class stack<elem>; // 设置stack为友元 private: elem data; stacknode * next; public: // 构造函数 stacknode(elem d, stacknode * n = NULL): data(d), next(n){} stacknode(stacknode * n = NULL):next(n){} }; ////////////////////////////////////// 链式栈类 ///////////////////////////////////////// template <typename elem> class stack { private: stacknode<elem> * top; int size; public: // 构造及销毁函数 stack(){init();} ~stack(){removeall();} void init(); void removeall(); // 判空 bool isempty(); // 入栈 bool pushhelp(const elem & pelem); void push(const elem & pelem); // 出栈 bool pophelp(); void pop(); // 取栈顶元素 bool gettophelp(elem & gelem); void gettop(elem & gelem); }; //////////////////////////////////////// 链式栈类 —— 成员函数的定义 ///////////////////////////////// /* * -> 构造函数: * 1. 这里不用调用形参。 * 2. 直接将stack类中的结点设为空,使栈空间内包含零个元素。 **/ template <typename elem> // 构造函数 void stack<elem>::init() { top = new stacknode<elem>(NULL); size = 0; return; } /* * -> 栈的析构函数 * 1. 这里无形参。 * 2. 将栈空间清空,并将元素个数清零。 **/ template <typename elem> // 析构函数 void stack<elem>::removeall() { if (isempty()) return; else while (pophelp()); return; } /* * -> 判空函数 * 1. 这函数不用调用参数。 * 2. bool型函数,若栈为空,则返回真,否则,返回假。 **/ template <typename elem> // 判空 bool stack<elem>::isempty() { return ( 0 == size); } /* * -> 入栈函数 * 1. 该函数包含两个函数: * 2. 第一个是bool pushhelp(const elem & pelem),该函数主要完成将元素放入栈中的任务, * 若放入栈失败,则返回false. * 3. 第二个是void push(),用于完成将元素放入栈中的功能,无论成功与否,给予用户提示。 */ template <typename elem> bool stack<elem>::pushhelp(const elem & pelem) { if ( !( top = new stacknode<elem>(pelem, top)) ) // 先将新元素赋给新结点,再将新结点的next指向原top,再将原top结点指向新结点 // 即 假设原来栈内刚刚构造完为 [地址1(空元素,NULL)] // 现使用(元素1)插入进栈,那么插入: // 第一步小步骤:赋元素( new 里面的(pelem))|||即 [地址1(空元素,NULL)] -> [地址2(元素1,NULL)] // 第二步小步骤:赋地址( new 里面的(,top) )|||即 [地址1(空元素,NULL)] -> [地址2(元素1, top(即地址1))] // 第三步小步骤:赋新地址(top = new...)|||即 [地址2(元素1,地址1)] -> [地址1(空元素, NULL)] // 这就相当于使用了链表中的前插法。 return false; ++size; return true; } template <typename elem> void stack<elem>::push(const elem & pelem) { cout << "\n" << (pushhelp(pelem) ? "恭喜,成功将元素" : "失败插入元素 ") << pelem << " 入栈\n"; return; } /* * -> 出栈函数 * 1. 该函数包含两个函数: * 2. 第一个是bool pophelp()该函数主要完成将元素出栈的任务。 * 3. 第二个是void pop(), 用于完成将元素出栈的任务,无论成功与否,给予用户提示。 **/ template <typename elem> bool stack<elem>::pophelp() { if (isempty()) return false; // 根据元素入栈时的原理,指针从栈顶不断地指向next,最终会指向栈底遇上NULL指针 // 所以,在删除时,只需要不断地删除top指针就可以了。 stacknode<elem> * temp = top -> next; delete top; top = temp; --size; return true; } template <typename elem> void stack<elem>::pop() { cout << "\n" << (pophelp() ? "恭喜,成功" : "失败 ") << " 将元素出栈\n"; return; } /* * -> 取栈顶元素 * 1. bool gettophelp(elem & gelem); 将形参设置为引用。 * 2. 将此函数设为bool类型,若成功,将取得的栈顶元素放到gelem中,返回true. * 3. 若失败,不往元素中放入东西,并且返回false. * 4. void gettop(elem & gelem);跟上面函数相对应,也是将元素放入gelem中,这个函数不同点是会给用户给出提示。 **/ template <typename elem> bool stack<elem>::gettophelp(elem & gelem) { if (isempty()) return false; else gelem = top -> data; return true; } template <typename elem> void stack<elem>::gettop(elem & gelem) { if (gettophelp(gelem)) cout << "\n获取元素成功:获得的栈顶元素为" << gelem << "\n"; else cout << "\n获取元素失败!\n"; return; } //////////////////////////////////////////////////// 主函数 ///////////////////////////////////////////// int main() { // 开始测试链式栈 cout << "\n ----------------------- 现在开始对链式栈小程序进行测试 -----------------------\n\n"; stack<int> test; cout << "\n\n -> 入栈测试开始(使用循环语句向栈中插入10个元素)\n\n"; for (int i = 0; i != 10; ++i) { cout << "第 " << i + 1 << "次: "; test.push(i); } int temp; cout << "\n\n -> 获取栈顶元素测试\n\n"; test.gettop(temp); cout << endl; cout << "\n\n -> 出栈测试开始(使用循环语句向栈中提取11个元素)\n\n"; // 栈中一共只有10个元素,测试最后一次是否会提取失败 for (int i = 0; i != 11; ++i) { cout << "第 " << i + 1 << "次: "; test.pop(); } cout << endl; system("pause"); return 0; }
运行结果:
----------------------- 现在开始对链式栈小程序进行测试 ----------------------- -> 入栈测试开始(使用循环语句向栈中插入10个元素) 第 1次: 恭喜,成功将元素0 入栈 第 2次: 恭喜,成功将元素1 入栈 第 3次: 恭喜,成功将元素2 入栈 第 4次: 恭喜,成功将元素3 入栈 第 5次: 恭喜,成功将元素4 入栈 第 6次: 恭喜,成功将元素5 入栈 第 7次: 恭喜,成功将元素6 入栈 第 8次: 恭喜,成功将元素7 入栈 第 9次: 恭喜,成功将元素8 入栈 第 10次: 恭喜,成功将元素9 入栈 -> 获取栈顶元素测试 获取元素成功:获得的栈顶元素为9 -> 出栈测试开始(使用循环语句向栈中提取11个元素) 第 1次: 恭喜,成功 将元素出栈 第 2次: 恭喜,成功 将元素出栈 第 3次: 恭喜,成功 将元素出栈 第 4次: 恭喜,成功 将元素出栈 第 5次: 恭喜,成功 将元素出栈 第 6次: 恭喜,成功 将元素出栈 第 7次: 恭喜,成功 将元素出栈 第 8次: 恭喜,成功 将元素出栈 第 9次: 恭喜,成功 将元素出栈 第 10次: 恭喜,成功 将元素出栈 第 11次: 失败 将元素出栈 请按任意键继续. . .