(2011.10.30)3_a2.cpp —— 链式栈的定义

 源程序:

// 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次:
失败  将元素出栈

请按任意键继续. . .


 

你可能感兴趣的:((2011.10.30)3_a2.cpp —— 链式栈的定义)