下面是源代码:
// 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
销毁操作成功。
请按任意键继续. . .