数据结构实验3 单链表的基本操作实现

姓名:Far_Rainbow
学号: 202505000X
专业: 软件工程
年级:2020级

实验名称:实验3 单链表的基本操作实现

实验内容

(1)实验目的
通过该实验,深入理解链表的逻辑结构、物理结构等概念,掌握链表基本操作的编程实现,熟练掌握C语言中指针的操作。和实验2对比,掌握线性结构两种不同存储方式的区别。

(2)实验内容
编程实现链表下教材第二章定义的线性表的基本操作,最好用菜单形式对应各个操作,使其编程一个完整的小软件。注意,每个功能模块一定要考虑非法的情况,并作出相应的提示,例如:求前驱,要分别能够测试第一个元素的前驱、其他正常的元素的前驱、输入一个在表中不存在的元素求其前驱,这三种情况应给出相应的提示语和结果值;插入和删除时要考虑插入或删除的位置是否合法等。

(3)实验要求:
菜单项包括:

  1. 初始化或重置链表
  2. 销毁链表
  3. 清空链表
  4. 链表长度
  5. 指定位置的元素值
  6. 链表已存在元素的位序
  7. 求输入元素的直接前驱
  8. 求输入元素的直接后继
  9. 在第i个位置插入一个元素
  10. 删除第i个元素
  11. 输出有的链表元素
  12. 初始化并用头插法(或尾插法)输入元素
  13. 实现单链表的逆序存放
    要求:所有的提示语和输出语句不允许出现在自定义的函数中,只能在main函数中出现提示语。
    注:销毁链表时需要循环释放每个结点所占用的空间。
    注:求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值。

(4)验收/测试用例
参考实验2

实验类型:验证性

实验的重难点:链表的定义和实现

实验环境:TDM-GCC 4.9.2 64-bit

实验步骤及完成任务情况

一、设计思想

  1. 采用模板实现泛型编程,可创建任意数据类型的单链表;
  2. 采用链式存储方式,插入删除时间复杂度都是 O ( 1 ) O(1) O(1)

二、主要源代码

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

template <typename T> struct Lnode {
	T data;
	Lnode<T>* next;
};

template <typename T> class List {
private:
	int _length;
	Lnode<T>* header;
	
public:
	void init() {header = new Lnode<T>; header->next = NULL; _length = 0;}
	void destroy();
	void clear();
	List() {header = NULL; }
	~List() {destroy(); }
	bool exist() const {return header != NULL ? 1 : 0;} 
	bool isempty() const {return _length > 0 ? 0 : 1; }
	int getlength() const {return _length; }
	Lnode<T>* find(int pos);
	int elemlocate(T const& e);
	Lnode<T>* priornode(T const& e);
	Lnode<T>* nextnode(T const& e);
	Lnode<T>* insert(int pos, T const& e);
	T remove(int pos);
	void traverse();
	void create(int n);
	Lnode<T>* reverse();
};

template <typename T> void List<T>::destroy()
{
	if (!exist())	return;
	Lnode<T>* p = header, *q;
	while(p){
		q = p->next;
		delete p;
		p = q;
	}
	header = NULL;
	_length = 0;
}

template <typename T> void List<T>::clear()
{
	Lnode<T>* p = header->next, *q;
	while(p){
		q = p->next;
		delete p;
		p = q;
	}
	_length = 0;
}

template <typename T> Lnode<T>* List<T>::find(int pos)
{
	int count = 0;
	Lnode<T>* p = header->next;
	while(p){
		count ++;
		if(count == pos)	return p;
		p = p->next;
	}
	return NULL;
}

template <typename T> int List<T>::elemlocate(T const& e)
{
	int count = 0;
	Lnode<T>* p = header->next;
	while(p)
	{
		count ++;
		if(p->data == e)	return count;
		p = p->next;
	}
	return 0;
}

template <typename T> Lnode<T>* List<T>::priornode(T const& e) //
{
	Lnode<T>* p = header->next, *q;
	while(p)
	{
		q = p->next;
		if(q && q->data == e)	return p;
		p = q;
	}
	return NULL;
}

template <typename T> Lnode<T>* List<T>::nextnode(T const& e) //
{
	Lnode<T>* p =header->next, *q;
	while(p){
		q = p->next;
		if(q && p->data == e)	return q;
		p = q;
	}
	return NULL;
}

template <typename T> Lnode<T>* List<T>::insert(int pos, T const& e)
{
	int count = 0;
	Lnode<T>* p = header; //注意考虑插入到首元结点的位置,故不用p=header->next; 
	Lnode<T>* q = new Lnode<T>;
	q->data = e;
	while(p){
		count ++;
		if(count == pos){
			q->next = p->next;
			p->next = q;
			++ _length;
			return q;
		}
		p = p->next;
	}
	return NULL;
}

template <typename T> T List<T>::remove(int pos) // 删不了第一个元素 和非法情况 
{
	int count = 0;
	Lnode<T>* p = header->next, *q;
	while(p)
	{
		q = p->next;
		count ++;
		if(count == pos-1){
			p->next = q->next;
			T e = q->data;
			delete q;
			-- _length;
			return e ;
		}
		p = q;
	}
}

template <typename T> void List<T>::traverse()
{
	Lnode<T>* p = header->next;
	while(p){
		cout<<p->data<<' ';
		p = p->next;
	}
}

template <typename T> void List<T>::create(int n)
{
	Lnode<T>* p;
	while(n --)
	{
		p = new Lnode<T>;
		cout<<"请输入想要插入的值:";
		cin>>p->data;
		p->next = header->next;
		header->next = p;
		++ _length;
	}
}

template <typename T> Lnode<T>* List<T>::reverse()
{
	if(header == NULL || header->next == NULL)	return header;
	Lnode<T>* now = header->next, *pre = NULL, *next = NULL;
	while(now){
		next = now->next;
		now->next = pre;
		pre = now;
		now = next;
	}
	header->next = pre;
	return header;
}

int main()
{
	cout<<"\n   基单链表的基本操作实现\n\n";
	cout<<"1---初始化一个单链表\n";
	cout<<"2---销毁单链表\n";
	cout<<"3---清空单链表\n";
	cout<<"4---求单链表长度\n";
	cout<<"5---获取线性表中指定位置的元素\n";
	cout<<"6---获取单链表元素的位置\n";
	cout<<"7---求前驱\n";
	cout<<"8---求后继\n";
	cout<<"9---在单链表指定位置插入元素\n";
	cout<<"10--删除单链表指定位置的元素\n";
	cout<<"11--显示单链表\n";
	cout<<"12--初始化并用头插法输入元素\n";
	cout<<"13--实现单链表的逆序存放\n"; 
	cout<<"\n\t退出,输入一个负数!\n\n";
	List<int> L;
	while(true)
	{
		int myOption;
		cout<<"\n请输入操作序号:";
		cin>>myOption;
		switch(myOption){
			case 1:{
				if(L.exist()){
					cout<<"初始化失败,单链表已存在!\n";
					break; 
				}
				L.init();
				cout<<"初始化成功!\n";
				break;
			}
			case 2:{
				if (!L.exist()){
					cout<<"销毁失败,单链表不存在\n";
					break; 
				}
				L.destroy();
				cout<<"销毁成功!\n";
				break;
			} 
			case 3:{
				if (!L.exist()){
					cout<<"清空失败,单链表不存在\n";
					break; 
				}
				if (L.isempty()) ; 
				else	L.clear();
				cout<<"清空成功!\n"; 
				break;
			}
			case 4:{
				if (!L.exist()){
					cout<<"请先创建单链表!\n";
					break; 
				}
				cout<<"单链表的长度是"<<L.getlength()<<endl; 
				break;
			}
			case 5:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空,请先插入元素!\n";
					break;
				}
				cout<<"请输入你要获取元素的位置:";
				int pos;
				cin>>pos;
				Lnode<int>* ptr = L.find(pos);
				if (!ptr) {
					cout<<"不存在该位置的元素\n";
					break;
				}
				cout<<"第"<<pos<<"位元素是 "<<ptr->data<<endl; 
				break;
			}
			case 6:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空,请先插入元素!\n";
					break;
				}
				cout<<"请输入您要获取位置的元素:";
				int e;
				cin>>e;
				if (!L.elemlocate(e)){
					cout<<"单链表中不存在该元素!\n";
					break;
				}
				cout<<"元素"<<e<<"的位置是"<<L.elemlocate(e)<<endl; 
				break;
			}
			case 7:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空,请先插入元素!\n";
					break;
				}
				cout<<"请输入您要获取前驱的元素:";
				int pos, e;
				cin>>e;
				Lnode<int>* ptr = L.priornode(e);
				if (!ptr){
					cout<<"获取失败,该元素不存在或无前驱!\n";
					break; 
				}
				cout<<"元素"<<e<<"的前驱元素是"<<(ptr-1)->data<<endl;
				break;
			}
			case 8:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空,请先插入元素!\n";
					break;
				}
				cout<<"请输入您要获取后继的元素:";
				int e;
				cin>>e;
				Lnode<int>* ptr = L.nextnode(e);
				if (!ptr){
					cout<<"获取失败,该元素不存在或无后继!\n";
					break; 
				}
				cout<<"元素"<<e<<"的后继元素是"<<(ptr+1)->data<<endl;
				break;
			}
			case 9:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				cout<<"请输入指定位置:";
				int pos;
				cin>>pos;
				cout<<"请输入想要插入的值:";
				int e;
				cin>>e;
				if (!L.insert(pos, e)){
					cout<<"插入失败,请重新尝试!\n";
					break;
				}
				else	cout<<"插入完毕!\n";
				break;
			}
			case 10:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空!\n";
					break;
				}
				cout<<"请输入你要删除的元素的位置:";
				int pos;
				cin>>pos;
				int e = L.remove(pos);
				if (!e){
					cout<<"删除失败,请重新尝试!\n";
					break;
				}
				else	cout<<"删除完毕!"<<"被删除的元素是"<<e<<endl;;
				break;
			}
			case 11:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空!\n";
					break;
				}
				cout<<"单链表的所有元素是:";
				L.traverse();
				cout<<endl;
				break;
			} 
			case 12:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				cout<<"请输入你想插入的元素个数:";
				int n;
				cin>>n;
				L.create(n);
				break;
			} 
			case 13:{
				if (!L.exist()){
					cout<<"单链表不存在,请先创建单链表!\n";
					break; 
				}
				if (L.isempty()){
					cout<<"单链表为空!\n";
					break;
				}
				cout<<"逆置前的单链表为:";
				L.traverse();
				cout<<endl<<"逆置后的单链表为:";
				L.reverse();
				L.traverse();
				cout<<endl;
				break;
			}
		}
		if(myOption >13 || myOption == 0)	cout<<"\n请输入小于13的正整数\n\n";
		if(myOption < 0){
			cout<<"\n退出程序!\n";
			break;
		}
	} 
	return 0;
}
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值