(2011.09.30)2_a3.cpp -- 对单链表的定义

 下面是源代码:
// 2_a3.cpp -- 对单链表的定义

/** 
 * 程序要求:
 * 对单链表的定义
 * 完成对单链表结构的定义,以及对单链表的各种基本运算的实现(每种基本运算用一个函数来实现)。
 * 基本运算包括:
 * 建表Create运算、初始化InitList运算、求表长Length运算、插入新节点Insert运算、删除节点Delete运算、按序号查找Get运算、定位(按值查找)Locate运算、输出单链表中所有结点的数据元素值Display运算、销毁Destroy运算。
 * 并且在main函数中分别调用以上各种基本运算的函数来使用,以证明其功能已实现。
 * 此题的源程序保存为 2_a3.cpp。
 */


#include <iostream>
using std::cout;
using std::cerr;

template <typename element> class node
{
public:
	element elem;
	node * next;
	node (element e, node * n = NULL): elem(e), next(n){}
	node (node * n = NULL) : next(n){}
};

template <typename element> class llist:public node<element>
{
private:
	node<element> * head;			// 指向头指针
	node<element> * fence;			// 指向当前指针
	node<element> * tail;			// 指向尾指针
	int leftcnt;					// 链表的左长度
	int allcnt;						// 链表的总长度

	void init() 					// 用于新建链表时初始化
	{
		head = new node<element>();			// 带头结点的单链表
		fence = head;
		tail = fence;
		leftcnt = 0;
		allcnt = 0;
		return;
	}
	void removeall()				// 用于删除表中所有的元素
	{
		while( head != NULL)
		{
			fence = head;
			head = head -> next;
			cerr<< "\n删除前\t";
			cerr << "\tfence: " << fence ;
			cerr << "\thead: " << head ;
			delete fence;
			cerr<< "\n删除后\t";
			cerr << "\tfence: " << fence;
			cerr << "\thead: " << head;
		}
		return;
	}
	bool inserthelp(const element&, const int &);
	bool findhelp(const element &);

public:
	llist(){init();}				// 构造一个带空表头的单链表
	~llist(){removeall();}			// 析构函数

	// 定位的操作
	void setstart();
	void setend();
	bool setpos(const int &);

	// 一般的数据添删查找操作
	void insert(const element &, const int &);
	void append(const element &);
	void del(const element &);
	void del(const int &);
	void find(const element &);
	void remove(){removeall();}

	// 遍历
	void printall();
};

/**
 * 定位的操作:
 * setstart()为设置起点;
 * setend()为设置终点;
 * setpos(const int &)则根据输入的整型设置指定位置。
 * 注意:定位时,形参统一使用从1数起的数,因为这个单链表设置有头结点,写程序时需注意。
 */

template<typename element> 
void llist<element>::setstart()				// 设置起点
{
	leftcnt = 0;
	fence = head;
	return;
}

template<typename element> 
void llist<element>::setend()
{
	leftcnt = allcnt;
	fence = tail;
	return;
}

template<typename element> 
bool llist<element>::setpos(const int & pos)	// 此函数将fence设为pos的前一位,方便其它操作。
{
	if (pos < 1 || pos > allcnt)			// 考虑超出范围
		return false;
	else
	{
		int pos2 = pos - 1;
		fence = head;
		leftcnt = 0;
		int i(0);
		for (; i != pos2; ++i)
		{
			fence = fence -> next;
			leftcnt++;
		}
	}
	return true;
}


/**
 * 插入操作:包含两个函数
 * inserthelp()用于判断是否能正确插入。
 * insert()用于插入时提供给用户的行为。
 * append()直接从尾部插入。
 */
template<typename element> 
bool llist<element>::inserthelp(const element & elem, const int & pos)
{
	if (setpos(pos) == false)
		return false;
	// 调用setpos()时已将位置调对,假如pos为3,则此时在链表中下标为1,插入到链表的位置2
	fence -> next = new node<element>(elem, fence -> next);
	if (tail == fence)
		tail = fence -> next;
	++allcnt;
	++leftcnt;
	return true;
}

template<typename element> 
void llist<element>::insert(const element & elem, const int &pos)
{
	if (inserthelp(elem,pos) == false)
		cerr << "\n插入错误,请检查输入的位置是否正确。";
	else
		cout << "\n恭喜,已在 " << pos << "位置正确插入 " << elem << " 元素。";
	return;
}

template<typename element> 
void llist<element>::append(const element & elem)
{
	setend();
	fence -> next = new node<element>(elem, fence -> next);
	tail = fence -> next;
	++allcnt;
	++leftcnt;
	cout << "\n恭喜,已在尾部正确插入元素 " << elem << " 。";
	return;
}
/**
 * 查找操作:
 * findhelp()当查找出该元素时,直接插入,当查找失败时,返回false;
 * find()用户提醒相关操作。
 */

template<typename element> 
bool llist<element>::findhelp(const element & felem)
{
	setstart();
	while(fence -> next != NULL)
	{
		++leftcnt;
		if (fence -> next -> elem == felem)
			return true;
		fence = fence -> next;
	}
	// 当遍历链表仍未返回真时,说明找不到该元素
	return false;
}


template<typename element> 
void llist<element>::find(const element & elem)
{
	if (findhelp(elem) ==  false)
		cerr << "\n未找到元素。";
	else
		cout << "\n在链表中第 " << leftcnt << " 位置中发现该元素。";
	return;
}

/**
 * 数据删除操作:
 * 该操作用户可能通过元素的输入或位置的输入操作。
 * 当选择使用位置删除时,程序将会借助setpos函数和findhelp函数进行操作。
 */

template<typename element> 
void llist<element>::del(const element & elem)
{
	if (head == tail) // 当此为空表时
	{
		cout << "\n未从表中发现元素。";
		return;
	}
	if (findhelp(elem) == false) // 当未找到该元素时
	{
		cout << "\n未从表中发现元素。";
		return;
	}
	// 考虑删除的位置是否在尾结点
	if (fence -> next == tail)
	{
		delete fence -> next;
		fence -> next = NULL;
		tail = fence;
		--allcnt;
		cout << "\n恭喜,删除成功。";
		return;
	}
	node<element> * temp = fence -> next;
	fence -> next = fence -> next -> next;
	delete temp;
	--allcnt;
	cout << "\n恭喜,删除成功。";
	return;
}

template<typename element> 
void llist<element>::del(const int & pos)
{
	if (head == tail) // 当找现为空表或元素定位错误时
	{
		cout << "\n未从表中发现元素。";
		return;
	}
	if(false == setpos(pos)) // 当找现为空表或元素定位错误时
	{
		cout << "\n未从表中发现元素。";
		return;
	}
	// 考虑删除的位置是否在尾结点
	if (fence -> next == tail)
	{
		delete fence -> next;
		fence -> next = NULL;
		tail = fence;
		--allcnt;
		cout << "\n恭喜,删除成功。";
		return;
	}
	node<element> * temp = fence -> next;
	fence -> next = fence -> next -> next;
	delete temp;
	--allcnt;
	cout << "\n恭喜,删除成功。";
	return;
}

// 遍历链表并按一定格式输出
template<typename element> 
void llist<element>::printall()
{
	int num(allcnt);
	if(num == 0)
	{
		cout << "\n未从该链表中发现元素。";
		return;
	}
	setstart();
	cout << "\n该链表中共有 " << allcnt << " 个元素。";
	for(fence = fence -> next; leftcnt != allcnt; ++leftcnt, fence = fence -> next)
	{
		cout << "\n第 " << leftcnt + 1 << " 个: " 
			<< "\t地址是: " << fence << " \t元素是: " << fence -> elem;
		cerr << "\t下一地址是:" << fence -> next;
	}
	return;
}


// 主函数--测试开始
int main()
{
  // 初始化链表
	cout << "_______________________________链表测试开始________________________________\n";
	llist<char> test;

  // 遍历
	test.printall();
		system("pause");

  // 插入操作
	cout << "\n\n------------------------------>  开始插入操作  <------------------------------\n";
	void insertin(llist<char> &);
	insertin(test);
	test.printall();
	cout << '\n';
	system("pause");

  // 删除操作
	cout << "\n\n------------------------------>  开始删除操作  <------------------------------\n";
	void del(llist<char> &);
	del(test);
	test.printall();
	cout << '\n';
	system("pause");

  // 查找操作
	cout << "\n\n------------------------------>  开始查找操作  <------------------------------\n";
	void search(llist<char> &);
	search(test);
	test.printall();
	cout << '\n';
	system("pause");

  // 销毁操作
	cout << "\n\n------------------------------>  开始销毁操作  <------------------------------\n";
	test.remove();
	cout << "\n销毁操作成功。";

	cout << '\n';
	system("pause");
	return 0;
}


/**
 * 插入操作:
 * 尝试使用append和insert操作。
 */
void insertin(llist<char> & list)
{
	cout << "\n先用for使用append函数连续插入8个元素:\n";
	int i(0);
	char t('8');
	for (; i != 8; ++i, --t)
		list.append(t);
	list.printall();
	// 尝试错误插入
	cout << "\n尝试在位置10错误插入:\n";
	list.insert('0', 10);
	// 正确插入
	cout << "\n尝试在正确的位置插入:\n";
	list.insert('8', 8);
	list.insert('9', 9);
	return;
}

/**
 * 查找操作:
 * 查找第一个元素,最后一个元素,及中间的元素,不存在的元素。
 */
void search(llist<char> & list)
{
	cout << "\n先查找第一个元素'8':";
	list.find('8');
	cout << "\n再查找最后一个元素'1':";
	list.find('1');
	cout << "\n查找中间的元素'1':";
	list.find('5');
	cout << "\n查找不存在的元素'A':";
	list.find('A');
	return;
}

/**
 * 数据删除操作:
 * 删除第一位的数据,删除最后一位的数据,删除中间的元素,删除不存在的元素。
 */

void del(llist<char> &list)
{
	cout << "\n先删除第一个元素'8':";
	list.del('8');
	list.printall();
	cout << "\n再删除最后一个元素'1':";
	list.del('1');
	list.printall();
	cout << "\n删除中间的元素'5':";
	list.del('5');
	list.printall();
	cout << "\n以位置方式删除第一个元素:";
	list.del(1);
	list.printall();
	cout << "\n以位置方式删除第六个元素:";
	list.del(6);
	list.printall();
	cout << "\n删除不存在的元素'A':";
	list.del('A');
		list.printall();
	return;
}


 下面是运行结果:

_______________________________链表测试开始________________________________

未从该链表中发现元素。请按任意键继续. . .


------------------------------>  开始插入操作  <------------------------------

先用for使用append函数连续插入8个元素:

恭喜,已在尾部正确插入元素 8 。
恭喜,已在尾部正确插入元素 7 。
恭喜,已在尾部正确插入元素 6 。
恭喜,已在尾部正确插入元素 5 。
恭喜,已在尾部正确插入元素 4 。
恭喜,已在尾部正确插入元素 3 。
恭喜,已在尾部正确插入元素 2 。
恭喜,已在尾部正确插入元素 1 。
该链表中共有 8 个元素。
第 1 个:        地址是: 006B4E38      元素是: 8     下一地址是:006B4E80
第 2 个:        地址是: 006B4E80      元素是: 7     下一地址是:006B4EC8
第 3 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F10
第 4 个:        地址是: 006B4F10      元素是: 5     下一地址是:006B4F58
第 5 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 6 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 7 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5030
第 8 个:        地址是: 006B5030      元素是: 1     下一地址是:00000000
尝试在位置10错误插入:

插入错误,请检查输入的位置是否正确。
尝试在正确的位置插入:

恭喜,已在 8位置正确插入 8 元素。
恭喜,已在 9位置正确插入 9 元素。
该链表中共有 10 个元素。
第 1 个:        地址是: 006B4E38      元素是: 8     下一地址是:006B4E80
第 2 个:        地址是: 006B4E80      元素是: 7     下一地址是:006B4EC8
第 3 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F10
第 4 个:        地址是: 006B4F10      元素是: 5     下一地址是:006B4F58
第 5 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 6 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 7 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 8 个:        地址是: 006B5110      元素是: 8     下一地址是:006B5158
第 9 个:        地址是: 006B5158      元素是: 9     下一地址是:006B5030
第 10 个:       地址是: 006B5030      元素是: 1     下一地址是:00000000
请按任意键继续. . .


------------------------------>  开始删除操作  <------------------------------

先删除第一个元素'8':
恭喜,删除成功。
该链表中共有 9 个元素。
第 1 个:        地址是: 006B4E80      元素是: 7     下一地址是:006B4EC8
第 2 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F10
第 3 个:        地址是: 006B4F10      元素是: 5     下一地址是:006B4F58
第 4 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 5 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 6 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 7 个:        地址是: 006B5110      元素是: 8     下一地址是:006B5158
第 8 个:        地址是: 006B5158      元素是: 9     下一地址是:006B5030
第 9 个:        地址是: 006B5030      元素是: 1     下一地址是:00000000
再删除最后一个元素'1':
恭喜,删除成功。
该链表中共有 8 个元素。
第 1 个:        地址是: 006B4E80      元素是: 7     下一地址是:006B4EC8
第 2 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F10
第 3 个:        地址是: 006B4F10      元素是: 5     下一地址是:006B4F58
第 4 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 5 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 6 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 7 个:        地址是: 006B5110      元素是: 8     下一地址是:006B5158
第 8 个:        地址是: 006B5158      元素是: 9     下一地址是:00000000
删除中间的元素'5':
恭喜,删除成功。
该链表中共有 7 个元素。
第 1 个:        地址是: 006B4E80      元素是: 7     下一地址是:006B4EC8
第 2 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F58
第 3 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 4 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 5 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 6 个:        地址是: 006B5110      元素是: 8     下一地址是:006B5158
第 7 个:        地址是: 006B5158      元素是: 9     下一地址是:00000000
以位置方式删除第一个元素:
恭喜,删除成功。
该链表中共有 6 个元素。
第 1 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F58
第 2 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 3 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 4 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 5 个:        地址是: 006B5110      元素是: 8     下一地址是:006B5158
第 6 个:        地址是: 006B5158      元素是: 9     下一地址是:00000000
以位置方式删除第六个元素:
恭喜,删除成功。
该链表中共有 5 个元素。
第 1 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F58
第 2 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 3 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 4 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 5 个:        地址是: 006B5110      元素是: 8     下一地址是:00000000
删除不存在的元素'A':
未从表中发现元素。
该链表中共有 5 个元素。
第 1 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F58
第 2 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 3 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 4 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 5 个:        地址是: 006B5110      元素是: 8     下一地址是:00000000
该链表中共有 5 个元素。
第 1 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F58
第 2 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 3 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 4 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 5 个:        地址是: 006B5110      元素是: 8     下一地址是:00000000
请按任意键继续. . .


------------------------------>  开始查找操作  <------------------------------

先查找第一个元素'8':
在链表中第 5 位置中发现该元素。
再查找最后一个元素'1':
未找到元素。
查找中间的元素'1':
未找到元素。
查找不存在的元素'A':
未找到元素。
该链表中共有 5 个元素。
第 1 个:        地址是: 006B4EC8      元素是: 6     下一地址是:006B4F58
第 2 个:        地址是: 006B4F58      元素是: 4     下一地址是:006B4FA0
第 3 个:        地址是: 006B4FA0      元素是: 3     下一地址是:006B4FE8
第 4 个:        地址是: 006B4FE8      元素是: 2     下一地址是:006B5110
第 5 个:        地址是: 006B5110      元素是: 8     下一地址是:00000000
请按任意键继续. . .


------------------------------>  开始销毁操作  <------------------------------

删除前          fence: 006B4DF0 head: 006B4EC8
删除后          fence: 006B4DF0 head: 006B4EC8
删除前          fence: 006B4EC8 head: 006B4F58
删除后          fence: 006B4EC8 head: 006B4F58
删除前          fence: 006B4F58 head: 006B4FA0
删除后          fence: 006B4F58 head: 006B4FA0
删除前          fence: 006B4FA0 head: 006B4FE8
删除后          fence: 006B4FA0 head: 006B4FE8
删除前          fence: 006B4FE8 head: 006B5110
删除后          fence: 006B4FE8 head: 006B5110
删除前          fence: 006B5110 head: 00000000
删除后          fence: 006B5110 head: 00000000
销毁操作成功。
请按任意键继续. . .


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值