源程序:
// 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次:
失败 将元素出栈
请按任意键继续. . .