【记录】【C++】数据结构实验课作业(二)

实验作业相关要求

实验二 单链表

一、实验目的与要求
1)熟悉单链表的类型定义;
2) 熟悉单链表的基本操作;
3)灵活应用链表解决具体应用问题。

二、实验内容
1)请设计一个单链表的存储结构,并实现单链表中基本运算算法。
编写程序实现单链表的各种基本运算(单链表元素类型可以自定义,如字符),并在此基础上设计主程序完成以下功能。
§ 创建单链表。
§ 依次插入a,b,c,d,e元素。
§ 输出单链表的元素和长度。
§ 判断单链表是否为空。
§ 输出单链表的第3个元素。
§ 输出元素a的位置。
§ 在第4个元素位置上插入f元素。
§ 删除单链表的第3个元素。

2)请设计一个学校职工个人信息管理程序,每个职工记录包含职工编号(no)、姓名(name)、部门号(depno)和工资数(salary)信息。设计一个单链表的存储结构,完成以下功能:
§ 从文件中读取职工记录,并建立一个带头结点的单链表L。
§ 输入一个职工记录。
§ 显示所有职工记录。
§ 按职工编号no对所有职工记录进行递增排序。
§ 按部门号depno对所有职工记录进行递增排序。
§ 按工资数salary,对所有职工记录进行递增排序。
§ 删除指定职工号的职工记录。
§ 删除职工文件中的全部记录。
§ 将单链表中的所有职工记录存储到职工文件或数组中。

三、实验结果
1)请将调试通过的主要源代码粘贴在下面
2)简述算法步骤
S1:
S2:
S3:
3)请分析算法的时间复杂度

源代码

#include<iostream>
#include<string>
#include<fstream>
using namespace std;
//节点模板类 
template<class T>
class LinkNode{
	public:
		T val;
		LinkNode<T>* next;
		LinkNode() : next(NULL) {}
		LinkNode(T x) : val(x), next(NULL) {}
		LinkNode(T x, LinkNode<T> *next) : val(x), next(next) {}
};
//链表模板类 
template<class T>
class List: public LinkNode<T>{
public:
	List();
	List(LinkNode<T>* ano);
	~List();
	int getSize();
	void outAllelems();
	bool Insert(int pos,T val);
	bool Insert(T val);
	bool isEmpty();
	T outOneelem(int pos);
	int getPos(T val);
	bool remove(int pos);
	LinkNode<T>* getHeadnode();
private:
	LinkNode<T>* head;//本链表设置头结点
};
//初始化 
template<class T>
List<T>::List(){
	head=new LinkNode<T>();
}
template<class T>
List<T>::List(LinkNode<T>* ano){
	head=new LinkNode<T>();
	head->next=ano;
}
//置为空表 
template<class T>
List<T>::~List(){
	LinkNode<T>* temp=head->next;
	while(temp){
		LinkNode<T>* temp2=temp->next;
		delete temp;
		temp=temp2;
	}
}
//获取链表长度 
template<class T>
int List<T>::getSize(){
	if(!head->next){
		return 0;
	}
	LinkNode<T>* temp=head->next;
	int size=0;
	while(temp){
		size++;
		temp=temp->next;
	}
	return size;
}
//输出所有元素 
template<class T>
void List<T>::outAllelems(){
	if(!head->next){
		cout<<"List is empty!!!"<<endl;
		return;
	}
	LinkNode<T>* temp=head->next;
	while(temp){
		cout<<temp->val<<" ";
		temp=temp->next;
	}
	cout<<"\n";
}
//插在在第pos个元素前面 
template<class T>	
bool List<T>::Insert(int pos,T val){
	if(pos<=0){
		cerr<<"Error!!!\n";
			exit(-1);
	}else if(pos==1||!head->next){
		LinkNode<T>* newNode=new LinkNode<T>(val);
		if(!newNode){
			cerr<<"Error!!!\n";
			exit(-1);	
		}
		newNode->next=head->next;
		head->next=newNode;
	}else{
		LinkNode<T>* cur=head->next;
		for(int i=1;;i++,cur=cur->next){
			if(!cur){
				cerr<<"Wrong position!!"<<endl;
				return false;
			}
			if(pos==i+1){
				LinkNode<T>* newNode=new LinkNode<T>(val);
				if(!newNode){
					cerr<<"Error!!!\n";
					exit(-1);	
				}
				newNode->next=cur->next;
				cur->next=newNode;
				break;
			}
		}
	}
	return true;
}
//后插一个元素 
template<class T>
bool List<T>::Insert(T val){
	if(!head->next){
		return Insert(1,val);
	}
	int size=getSize();
	return Insert(size+1,val);
}
//判断链表是否为空 
template<class T>
bool List<T>::isEmpty(){
	if(!head->next){
		return true;
	}else{
		return false;
	}
}
//获取某个位置的元素 
template<class T>
T List<T>::outOneelem(int pos){
	if(pos<=0||isEmpty()){
		cout<<"error"<<endl;
		exit(-1);
	}else{
		LinkNode<T>* cur=head->next;
		for(int i=1;;i++,cur=cur->next){
			if(!cur){
				cout<<"error"<<endl;
				exit(-1);
			}
			if(i==pos){
				return cur->val;
			}
		}
	}
}
//获得某个元素的位置 
template<class T>
int List<T>::getPos(T val){
		LinkNode<T>* cur=head->next;
		for(int i=1;bool(cur);i++,cur=cur->next){
			if(cur->val==val){
				return i;
			}
		}
		cerr<<"not found the elem!!"<<endl;
		exit(-1);
}
//删除某个位置的元素 
template<class T>
bool List<T>::remove(int pos){
	if(pos<=0){
		cerr<<"position error"<<endl;
		exit(-1);
	}else if(isEmpty()){
		cout<<"No member in List to be deleted!!"<<endl;
		return false;
	}else if(pos==1){
		LinkNode<T>* del=head->next;
		head->next=del->next;
		delete del;
		return true;
	}else{
		LinkNode<T>* cur=head->next;
		for(int i=1;;i++,cur=cur->next){
			if(!cur->next){
				cerr<<"Beyound range!!"<<endl;
				exit(-1);
			}
			if(pos==i+1){
				LinkNode<T>* del=cur->next;
				cur->next=del->next;
				delete del;
				break;
			}
		}
	}
	return true;
}
//获取头结点 
template<class T>
LinkNode<T>* List<T>::getHeadnode(){
	return this->head;
}
//职工类 
class Emp{
private:
	int no;
	string name;
	int depno;
	int salary;
public:
	Emp(int nox=0,string namex="",int depnox=0,int salaryx=0):no(nox),name(namex),depno(depnox),salary(salaryx){}
	int getno();
	string getname();
	int getdepno();
	int getsalary();
	void setno(int nox);
	void setname(string namex);
	void setdepno(int depnox);
	void setsalary(int salaryx);
	void swap(Emp& ano);
	friend ostream& operator<<(ostream& out, Emp& obj);
};
//实现封装 
int Emp::getno(){
	return no;
}
string Emp::getname(){
	return name;
}
int Emp::getdepno(){
	return depno; 
}
int Emp::getsalary(){
	return salary;
}
void Emp::setno(int nox){
	this->no=nox;
}
void Emp::setname(string namex){
	this->name=namex;
}
void Emp::setdepno(int depnox){
	this->depno=depnox;
}
void Emp::setsalary(int salaryx){
	this->salary=salaryx;
}
//交换两条职工记录的信息 
void Emp::swap(Emp& ano){
	Emp mid(ano);
	ano.setno(this->no);
	ano.setname(this->name);
	ano.setdepno(this->depno);
	ano.setsalary(this->salary);
	this->setno(mid.getno());
	this->setname(mid.getname());
	this->setdepno(mid.getdepno());
	this->setsalary(mid.getsalary());
}
ostream& operator<<(ostream& out, Emp& obj){
	out<<"\n职工编号:"<<obj.getno()<<"\t姓名:"<<obj.getname()<<"\t部门编号:"<<obj.getdepno()<<"\t工资:"<<obj.getsalary();
	return out;
}
//main function
int main(){
	
	//第一题  
	
	//创建单链表,建立元素为字符类型的单链表 
	List<char>* list=new List<char>();
	cout<<"建立元素为字符类型的单链表\n";
	//依次插入a,b,c,d,e元素。
	list->Insert('a');
	list->Insert('b');
	list->Insert('c');
	list->Insert('d');
	list->Insert('e');
	cout<<"依次插入a,b,c,d,e元素\n";
	//输出单链表的元素和长度。
	cout<<"链表的长度为:"<<list->getSize()<<endl;
	cout<<"所有元素如下:\n";
	list->outAllelems();
	cout<<"\n"; 
	//判断单链表是否为空。
	cout<<"链表是否为空:"<<(list->isEmpty()?"yes":"no")<<endl;
	//输出单链表的第3个元素。
	cout<<"第三个元素为:"<<list->outOneelem(3)<<endl;
	//输出元素a的位置。
	cout<<"元素'a'的位置为:"<<list->getPos('a')<<endl;
	//在第4个元素位置上插入f元素。
	list->Insert(4,'f');
	cout<<"在第4个元素位置上插入f元素\n";
	//删除单链表的第3个元素。
	list->remove(3);
	cout<<"删除单链表的第3个元素\n";
	//显示最终链表的所有元素
	cout<<"显示最终链表的所有元素:\n";
	list->outAllelems();
	//销毁空间 
	delete list;
	cout<<"成功销毁链表\n"<<endl;
	 
	//第二题
	
	//从文件中读取职工记录,并建立一个带头结点的单链表L。
	ifstream fi("Employee records.txt", ios::in);
	string temp;
	fi>>temp;
	fi>>temp;
	fi>>temp;
	fi>>temp;
	List<Emp>* lt=new List<Emp>();
	cout<<"建立输入流,创建单链表\n";
	//输入一个职工记录。
	while(true){
		int nox=0;
		string namex="";
		int depnox=0;
		int salaryx=0;
		fi>>nox;
		fi>>namex;
		fi>>depnox;
		fi>>salaryx;
		if(nox==0&&namex==""&&depnox==0&&salaryx==0){
			break;
		}
		lt->Insert(Emp(nox,namex,depnox,salaryx));
	}
	cout<<"输入文档内所有职工信息\n";
	//显示所有职工记录。
	cout<<"显示所有职工记录:\n";
	lt->outAllelems();
	//按职工编号no对所有职工记录进行递增排序。
	cout<<"按职工编号no对所有职工记录进行递增排序\n";
	LinkNode<Emp>* cur=lt->getHeadnode()->next;
	while(cur){
		LinkNode<Emp>* temp=cur->next;
		while(temp){
			if(cur->val.getno()>temp->val.getno()){
				cur->val.swap(temp->val);
			}
			temp=temp->next;
		}
		cur=cur->next;
	}
	cout<<"排序后变为如下顺序记录:\n";
	lt->outAllelems();
	//按部门号depno对所有职工记录进行递增排序。
	cout<<"按部门号depno对所有职工记录进行递增排序\n";
	cur=lt->getHeadnode()->next;
	while(cur){
		LinkNode<Emp>* temp=cur->next;
		while(temp){
			if(cur->val.getdepno()>temp->val.getdepno()){
				cur->val.swap(temp->val);
			}
			temp=temp->next;
		}
		cur=cur->next;
	}
	cout<<"排序后变为如下顺序记录:\n";
	lt->outAllelems();
	//按工资数salary,对所有职工记录进行递增排序。
	cout<<"按工资数salary,对所有职工记录进行递增排序\n";
	cur=lt->getHeadnode()->next;
	while(cur){
		LinkNode<Emp>* temp=cur->next;
		while(temp){
			if(cur->val.getsalary()>temp->val.getsalary()){
				cur->val.swap(temp->val);
			}
			temp=temp->next;
		}
		cur=cur->next;
	}
	cout<<"排序后变为如下顺序记录:\n";
	lt->outAllelems();
	//删除指定职工号的职工记录。
	cout<<"删除指定职工号的职工记录\n";
	cout<<"请输入需要删除的员工记录所对应的的职工号:";
	int del;
	cin>>del;
	cur=lt->getHeadnode()->next;
	int pos=-1;
	for(int i=1;bool(cur);i++,cur=cur->next){
		if(cur->val.getno()==del){
			pos=i;
			break;
		}
	}
	if(pos==-1){
		cerr<<"Wrong number!"<<endl;
	}else{
		lt->remove(pos);
		cout<<"Successfully delete!"<<endl;
	}
	cout<<"删除记录后变为如下顺序记录:\n";
	lt->outAllelems();
	//删除职工文件中的全部记录。
	ofstream fo("Employee records.txt", ios::out);
	cout<<"删除职工文件中的全部记录\n";
	//将单链表中的所有职工记录存储到职工文件或数组中。 
	fo<<"no"<<"\tname"<<"\tdepno"<<"\tsalary"<<endl;
	cur=lt->getHeadnode()->next;
	while(cur){
		fo<<cur->val.getno()<<"\t"<<cur->val.getname()<<"\t"<<cur->val.getdepno()<<"\t"<<cur->val.getsalary()<<endl;
		cur=cur->next;
	}
	fo.close();
	cout<<"将单链表中的所有职工记录存储到职工文件中\n";
	
	//销毁链表空间
	delete lt; 
	cout<<"成功销毁职工记录链表\n";
	
	return 0;
}

职工文本初始信息
在这里插入图片描述

执行cpp的效果
在这里插入图片描述

在这里插入图片描述

文本被修改后
在这里插入图片描述

作业提交的文档内容

1)请将调试通过的主要源代码粘贴在下面

2)简述算法步骤:

第一题
S1:建立模板链表复合类,由一个LinkNode模板类(含结点的数据与指针,只有初始化操作)与其子类List模板类(有指向头结点的指针,同时含有一系列对链表的操作如插入、删除结点等)组成。
S2:完善模板类定义的各个成员函数。
S3:创建字符型链表类对象作为案例,对其进行一些列操作并展示在窗口。

第二题
S1:建立Emp职工信息类,完善成员函数实现封装操作、交换信息操作及友元输出操作。
S2:利用Emp类与第一题创建的链表模板类,创建职工信息链表类,利用文件输入流函数将一个个职工信息封装到Emp对象并将一个个Emp对象放入链表中。
S3:利用链表类与Emp类的成员函数与友元函数,对结点一系列操作,并最终利用文件输出流将修改过的职工信息输出到文档。

3)请分析算法的时间复杂度。
第一题:
获取链表长度的时间复杂度为O(n)
输出所有元素的时间复杂度为O(n)
插入结点的时间复杂度:前插O(1) 后插O(n)
判断链表是否为空的时间复杂度为O(1)
输出指定位置的元素的时间复杂度为O(n)
获取指定元素的位置的时间复杂度为O(n)
移除指定位置的结点的时间复杂度为O(n)
获取头结点的时间复杂度为O(1)

第二题:
输入职工记录的时间复杂度为O(n)
前插法将职工记录存入链表的时间复杂度为O(n)
后插法将职工记录存入链表的时间复杂度为O(n^2)
显示所有职工记录的时间复杂度为O(n)
三次递增排序(此处均采用了冒泡排序)的时间复杂度都为O(n^2)
删除指定职工号的职工记录的时间复杂度为O(n)
将职工记录全部存入文档的时间复杂度为O(n)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值