姓名:Far_Rainbow
学号: 202505000X
专业: 软件工程
年级:2020级
实验名称:实验3 单链表的基本操作实现
实验内容:
(1)实验目的
通过该实验,深入理解链表的逻辑结构、物理结构等概念,掌握链表基本操作的编程实现,熟练掌握C语言中指针的操作。和实验2对比,掌握线性结构两种不同存储方式的区别。
(2)实验内容
编程实现链表下教材第二章定义的线性表的基本操作,最好用菜单形式对应各个操作,使其编程一个完整的小软件。注意,每个功能模块一定要考虑非法的情况,并作出相应的提示,例如:求前驱,要分别能够测试第一个元素的前驱、其他正常的元素的前驱、输入一个在表中不存在的元素求其前驱,这三种情况应给出相应的提示语和结果值;插入和删除时要考虑插入或删除的位置是否合法等。
(3)实验要求:
菜单项包括:
- 初始化或重置链表
- 销毁链表
- 清空链表
- 链表长度
- 指定位置的元素值
- 链表已存在元素的位序
- 求输入元素的直接前驱
- 求输入元素的直接后继
- 在第i个位置插入一个元素
- 删除第i个元素
- 输出有的链表元素
- 初始化并用头插法(或尾插法)输入元素
- 实现单链表的逆序存放
要求:所有的提示语和输出语句不允许出现在自定义的函数中,只能在main函数中出现提示语。
注:销毁链表时需要循环释放每个结点所占用的空间。
注:求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值。
(4)验收/测试用例
参考实验2
实验类型:验证性
实验的重难点:链表的定义和实现
实验环境:TDM-GCC 4.9.2 64-bit
实验步骤及完成任务情况:
一、设计思想
- 采用模板实现泛型编程,可创建任意数据类型的单链表;
- 采用链式存储方式,插入删除时间复杂度都是 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;
}