北邮22信通一枚~
跟随课程进度每周更新数据结构与算法的代码和文章
持续关注作者 解锁更多邮苑信通专属代码~
获取更多文章 请访问专栏:
目录
1.实验要求:
根据线性表的抽象数据类型的定义,选择下面任一种链式结构实现线性表,并完成线性表的基本功能。
线性存储结构(五选一)
- 带头结点的单链表
- 不带头结点的单链表
- 循环链表
- 双链表
- 静态链表
要求:实现线性表的基本功能
构造:使用头插法、尾插法两种方法;
插入:要求建立的链表按照关键字从小到大有序(静态链表不要求该项)
要求:实现线性表的基本功能
删除 查找 获取电表长度 销毁 其他:可自行定义;
编写测试main()函数测试线性表的正确性。
***说明***
实现线性表的基本功能部分,是书上的基础内容。头插法和尾插法均在书上有相应的源代码,这里不做赘述。
关于赋值问题,需要说明的是,对于构造函数来说,一个程序不可能同时拥有使用头插法的构造函数和使用尾插法的构造函数,因为传递的参数都一样,无法构成函数重载。如果在定义构造函数的时候,同时定义了头插法构造函数和尾插法构造函数,程序会终止运行并报错,错误显示为linklist重复定义。所以,本代码构造函数使用的是头插法。但是由于题目要求,需要体现尾插法的构造函数,故将尾插法的构造函数在段注释中一并写出(见代码第53行)。
同时,对链表的赋值不仅仅可以通过构造函数来实现,通过普通的成员函数也可以同样实现。通过普通成员函数来实现的好处是,可以通过不同的函数名来区分不同的方法,使得头插法和尾插法同时体现在程序中。在本代码中,体现头插法的成员函数是headinsert()函数(见代码第72行),体现尾插法的成员函数是rearinsert()函数(见代码第73行)。
2.程序分析
2.1存储结构
本代码使用的存储结构是单链表,示意图如下:
2.2关键算法分析
2.2.1关键算法:
删除 查找 获取链表长度 销毁
2.2.2代码详细分析:
2.2.2.1查找函数:
2.2.2.1.1getpos()函数:
时间复杂度O(n);
用户输入要查询的信息在链表中的顺序;
定义指向首结点地址的指针;
遍历链表,直到到达指定顺序为止;
输出该指针所指的结点的数据域;
template<class temp>
void linklist<temp>::getpos()
{
cout << "请输入您要查询的同学在链表中的顺序:" << endl;
int sea;
cin >> sea;
node<temp>* p = this->front->next;
int j = 1;
while (p != NULL && j != sea)
{
p = p->next;
j++;
}
if (p != NULL && j == sea)
{
cout << "该同学的信息为:" << endl;
p->data.print();
}
else
{
cout << "未查询到结果" << endl;
}
}
2.2.2.1.2getfull()函数:
时间复杂度O(n);
定义一个指向首结点地址的指针;
遍历链表,实现方法同上;
直到到达指定顺序停止;
返回指针变量;
template<class temp>
node<temp>* linklist<temp>::getfull(int i)
{
node<temp>* p = this->front->next;
int j = 1;
while (p != NULL && j != i)
{
p = p->next;
j++;
}
return p;
}
2.2.2.2获取链表长度函数getlength()函数
时间复杂度O(n);
定义指向首结点地址的指针;
遍历链表,每经过一个有效结点,计数变量加1;
输出链表长度;
template <class temp>
void linklist<temp>::getlength()
{
node<temp>* p = this->front->next;
int cnt = 0;
while (p != NULL)
{
p = p->next;
cnt++;
}
cout << endl << "有效学生信息为" << cnt << "个" << endl << endl;
}
2.2.2.3删除函数
2.2.2.3.1按位置删除结点
时间复杂度:O(n)
获取删除位置的前一个结点的地址1(指针1);
定义指向要删除的结点的指针2;
将指针1所指向的结点的next指针
指向指针2所指向的结点的next指针;
删除指针2所指向的结点地址;
template<class temp>
void linklist<temp>::del(int i)
{
node<temp>* p = this->front;
if (i != 1)p = getfull(i - 1);
node<temp>* q = p->next;
p->next = q->next;
temp x = q->data;
delete q;
x.print();
}
2.2.2.3.2按值删除结点
时间复杂度:O(n)
定义指向有效起始位置(首结点)的指针;
遍历链表,寻找数据域相同的结点的前一个结点;
按照2.2.2.3.1方法删除链表结点;
template<class temp>
void linklist<temp>::del(temp x)
{
int flag = 0;
node<temp>* p = this->front;
while (p->next != NULL)
{
if (p->next->data == x)
{
node<temp>* q = p->next;
p->next = q->next;
delete q;
cout << "删除数据完毕!" << endl;
flag = 1;
break;
}
p = p->next;
}
if (flag == 0)
{
cout << "未查询到数据!" << endl;
}
}
2.2.2.4插入函数
2.2.2.4.1 insert(int i,temp x)函数
时间复杂度O(n);
获取链表中顺序为i的结点的前一个结点的地址,并用一个指针变量(指针1存储;
判断指针指向的地址是否为空;
如果指针指向的地址不为空:
新建结点,将数据域赋值为x,
新节点的next指针指向指针1next指针所指向的结点地址
指针1的next指针指向新建结点的地址;
template<class temp>
void linklist<temp>::insert(int i, temp x)
{
node<temp>* p = this->front;
if (i != 1)
p = getfull(i - 1);
if (p != NULL)
{
node<temp>* s = new node<temp>;
s->data = x;
s->next = p->next;
p->next = s;
}
else
{
cout << "插入位置错误!" << endl;
exit(0);
}
}
2.2.2.4.2insertbygrades(temp x)函数:
***声明***
因为题目中要求实现有序插入,故书写了这个函数;
本函数的实现没有调用成员函数insert(int i,temp x)
***声明完毕***
时间复杂度O(n);
定义指针指向链表头结点地址;
新建结点,数据域赋值为x;
遍历链表,将x值与每一个结点的数据域进行比较,
直到符合要求停止(即x大于数据域或者x小于数据域);
之后运用与insert函数相同的插入方法,将新建的结点插入到链表中;
template<class temp>
void linklist<temp>::insertbygrades(temp x)
{
node<temp>* p = this->front;
node<temp>* s = new node<temp>;
s->data = x;
s->next = NULL;
while (p->next != NULL)
{
if (p->next->data.getsum() > x.getsum())
p = p->next;
else
{
s->next = p->next;
p->next = s;
break;
}
}
if (p->next == NULL)
p->next = s;
}
2.2.2.4.3easyinsertbygrades(temp x)函数:
***声明***
因为题目中要求实现有序插入,故书写了这个函数;
本函数的实现调用了成员函数insert(int i,temp x),
故代码看起来会更清晰 一点;
***声明完毕***
时间复杂度O(n);
程序运行结果:
函数实现方法同上;主函数依次调用各种linklist的成员函数,实现各种类的功能;
template<class temp>
void linklist<temp>::easyinsertbygrades(temp x)
{
int ins = -1;
node<temp>*p = this->front->next;
while (p != NULL)
{
if (p->data > x)//调用了>的重载
{
ins++;
p = p->next;
}
else
{
ins++;
break;
}
}
insert(++ins, x);
}
3.完整代码:
#include<iostream>
using namespace std;
class student
{
private:
int ID;
string name;
double chinese;
double math;
public:
student()
{
this->ID = 0;
this->name = "un_known_name";
this->chinese = 0;
this->math = 0;
}
student(int ID, string name, double chinese, double math)
{
this->ID = ID;
this->name = name;
this->chinese = chinese;
this->math = math;
}
void getinfo(int, string, double, double);
double getsum() { return this->chinese + this->math; }
void print();
bool operator==(student& stu)
{
return (stu.ID == this->ID) ? true : false;
}
bool operator > (student& stu)
{
return (this->getsum() > stu.getsum()) ? true : false;
}
};
inline void student::getinfo(int ID, string name, double chinese, double math)
{
this->ID = ID;
this->name = name;
this->chinese = chinese;
this->math = math;
}
inline void student::print()
{
cout << "ID:" << this->ID << " name:" << this->name <<
" chinese:" << this->chinese << " math:" << this->math << endl;
}
template<class temp>
struct node
{
temp data;
node<temp>* next;
};
template<class temp>
class linklist
{
private:
node<temp>* front;
public:
linklist()
{
this->front = new node<temp>;
this->front->next = nullptr;
}
linklist(temp a[], int n);//构造函数使用的是头插法 //要求的
void headinsert(temp a[], int n);//非构造函数实现头插法 //要求的
void rearinsert(temp a[], int n);//非构造函数实现尾插法 //要求的
void addtorear(temp x);
~linklist(); //要求的
void getmax();
void getmin();
void getmaxandmin();
void getaverage();
void getlength(); //要求的
void printlist();
void getpos(); //要求的
node<temp>* getfull(int i); //要求的
void judge(temp);
void insert(int i, temp x);
void insertbygrades(temp x); //要求的
void easyinsertbygrades(temp x); //要求的
void del(int i); //要求的
void del(temp x);//重载 //要求的
};
template<class temp>
linklist<temp>::linklist(temp a[], int n)
{
this->front = new node<temp>;
this->front->next = NULL;
for (int i = n - 1; i >= 0; i--)
{
node<temp>* s = new node<temp>;
s->data = a[i];
s->next = this->front->next;
this->front->next = s;
}
}
//尾插法
/*
template<class temp>
linklist<temp>::linklist(temp a[], int n)
{
this->front = new node<temp>;
node<temp>* r = this->front();
for (int i = 0; i < n; i++)
{
node<temp>* s = new node<temp>;
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
}
*/
template <class temp>
void linklist<temp>::headinsert(temp a[], int n)
{
this->front = new node<temp>;
this->front->next = NULL;
for (int i = n - 1; i >= 0; i--)
{
node<temp>* s = new node<temp>;
s->data = a[i];
s->next = this->front->next;
this->front->next = s;
}
}
template<class temp>
void linklist<temp>::rearinsert(temp a[], int n)
{
this->front = new node<temp>;
node<temp>* r = this->front;
for (int i = 0; i < n; i++)
{
node<temp>* s = new node<temp>;
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
}
template<class temp>
void linklist<temp>::addtorear(temp x)
{
node<temp>* p = this->front->next;
while (p != NULL)
p = p->next;
node<temp>* s = new node<temp>;
s->data = x;
s->next = NULL;
p->next = s;
}
template<class temp>
linklist<temp>::~linklist()
{
node<temp>* p = this->front;
while (p != NULL)
{
this->front = p;
p = p->next;
delete this->front;
}
}
template<class temp>
inline void linklist<temp>::getmax()
{
cout << "成绩最高的同学的信息为:" << endl;
node<temp>* p = this->front->next;
node<temp>* q = p;
while (p != NULL)
{
if (p->data.getsum() > q->data.getsum())
q = p;
p = p->next;
}
if (q)
{
q->data.print();
}
else
{
cout << "error" << endl;
exit(0);
}
cout << endl;
}
template<class temp>
inline void linklist<temp>::getmin()
{
cout << "成绩最低的同学的信息为:" << endl;
node<temp>* p = this->front->next;
node<temp>* q = p;
while (p != NULL)
{
if (p->data.getsum() < q->data.getsum())
q = p;
p = p->next;
}
if (q)
{
q->data.print();
}
else
{
cout << "error" << endl;
exit(0);
}
cout << endl;
}
template<class temp>
inline void linklist<temp>::getmaxandmin()
{
node<temp>* p = this->front->next;
node<temp>* pmax = p;
node<temp>* pmin = p;
while (p != NULL)
{
if (p->data.getsum() > pmax->data.getsum())
pmax = p;
if (p->data.getsum() < pmin->data.getsum())
pmin = p;
p = p->next;
}
if (pmax == NULL || pmin == NULL)
{
cout << "error" << endl;
exit(0);
}
else
{
int flag = 0;
cout << "成绩最高的同学的信息为:" << endl;
pmax->data.print();
label:
{
cout << "请问您确定要查询成绩最低同学的信息吗?" <<
"如果继续查询,请按1;否则,请按0" << endl;
int confirm;
cin >> confirm;
if (confirm == 1)
cout << "成绩最低的同学的信息为:" << endl;
else if (confirm == 0)
cout << "没有最低分" << endl;
else if (confirm != 1 && confirm != 0)
{
cout << "输入错误" << endl;
flag == 1;
}
}
if (flag == 1)
goto label;
pmin->data.print();
cout << endl;
}
}
template <class temp>
void linklist<temp>::getaverage()
{
double sum = 0;
int cnt = 0;
node<temp>* p = this->front->next;
while (p != NULL)
{
sum += p->data.getsum();
cnt++;
p = p->next;
}
cout << "共有" << cnt << "名同学参加考试,平均成绩为" << sum / cnt << "分" << endl;
cout << endl;
}
template <class temp>
void linklist<temp>::getlength()
{
node<temp>* p = this->front->next;
int cnt = 0;
while (p != NULL)
{
p = p->next;
cnt++;
}
cout << endl << "有效学生信息为" << cnt << "个" << endl << endl;
}
template <class temp>
inline void linklist<temp>::printlist()
{
node<temp>* p = this->front->next;
while (p != NULL)
{
p->data.print();
p = p->next;
}
cout << endl;
}
template<class temp>
void linklist<temp>::getpos()
{
cout << "请输入您要查询的同学在链表中的顺序:" << endl;
int sea;
cin >> sea;
node<temp>* p = this->front->next;
int j = 1;
while (p != NULL && j != sea)
{
p = p->next;
j++;
}
if (p != NULL && j == sea)
{
cout << "该同学的信息为:" << endl;
p->data.print();
}
else
{
cout << "未查询到结果" << endl;
}
}
template<class temp>
node<temp>* linklist<temp>::getfull(int i)
{
node<temp>* p = this->front->next;
int j = 1;
while (p != NULL && j != i)
{
p = p->next;
j++;
}
return p;
}
template<class temp>
void linklist<temp>::judge(temp x)
{
node<temp>* p = this->front->next;
int flag = 0;
while (p != NULL)
{
if (p->data == x)
{
x.print();
cout << "查询结果相符" << endl;
flag = 1;
break;
}
}
if (flag == 0)
{
x.print();
cout << "查询结果不符" << endl;
}
}
template<class temp>
void linklist<temp>::insert(int i, temp x)
{
node<temp>* p = this->front;
if (i != 1)
p = getfull(i - 1);
if (p != NULL)
{
node<temp>* s = new node<temp>;
s->data = x;
s->next = p->next;
p->next = s;
}
else
{
cout << "插入位置错误!" << endl;
exit(0);
}
}
//不使用insert函数时的写法;
template<class temp>
void linklist<temp>::insertbygrades(temp x)
{
node<temp>* p = this->front;
node<temp>* s = new node<temp>;
s->data = x;
s->next = NULL;
while (p->next != NULL)
{
if (p->next->data.getsum() > x.getsum())
p = p->next;
else
{
s->next = p->next;
p->next = s;
break;
}
}
if (p->next == NULL)
p->next = s;
}
//使用insert时的写法
template<class temp>
void linklist<temp>::easyinsertbygrades(temp x)
{
int ins = -1;
node<temp>*p = this->front->next;
while (p != NULL)
{
if (p->data > x)//调用了>的重载
{
ins++;
p = p->next;
}
else
{
ins++;
break;
}
}
insert(++ins, x);
}
template<class temp>
void linklist<temp>::del(int i)
{
node<temp>* p = this->front;
if (i != 1)p = getfull(i - 1);
node<temp>* q = p->next;
p->next = q->next;
temp x = q->data;
delete q;
x.print();
}
//重载
template<class temp>
void linklist<temp>::del(temp x)
{
int flag = 0;
node<temp>* p = this->front;
while (p->next != NULL)
{
if (p->next->data == x)
{
node<temp>* q = p->next;
p->next = q->next;
delete q;
cout << "删除数据完毕!" << endl;
flag = 1;
break;
}
p = p->next;
}
if (flag == 0)
{
cout << "未查询到数据!" << endl;
}
}
int main()
{
system("color 0A");
student stu[4];
int ID; string name; double chinese; double math;
cout << "1.请分别输入学生的ID,姓名,语文成绩,数学成绩,每个同学的信息占一行" << endl;
for (int i = 0; i < 4; i++)
{
cin >> ID >> name >> chinese >> math;
stu[i].getinfo(ID, name, chinese, math);
}
linklist<student>list(stu, 4);
list.getmax();
list.getmin();
//list.getmaxandmin();
list.getaverage();
list.getpos();
list.judge(stu[0]);
//测试insert函数和del函数
cout << endl << "2.下面测试insert和del函数:" << endl << endl;
student record(8, "lv", 66, 55);
cout << "3.插入的数据为:" << endl;
record.print();
list.insert(1, record);
cout << endl << "4.插入后,进行成绩查询:" << endl << endl;
list.getmaxandmin();
cout << endl << "5.删除的数据为第一个元素:" << endl << endl;
list.del(1);
cout << endl << "6.删除后的成绩表为:" << endl << endl;
list.printlist();
cout << endl << "7.删除后,进行成绩查询:" << endl << endl;
list.getmaxandmin();
cout << endl << "8.下面测试删除函数的重载函数:" << endl << endl;
cout << "9.删除的元素为:" << endl;
stu[0].print();
list.del(stu[0]);
cout << endl << "10.删除后的成绩表为:" << endl << endl;
list.printlist();
cout << endl << "11.删除后,进行成绩查询:" << endl << endl;
list.getmaxandmin();
cout << endl << "12.按顺序添加:" << endl << endl;
list.insertbygrades(record);
cout << endl << "添加后的结果为:" << endl << endl;
list.printlist();
cout << endl << "13.调用linkist函数成员insert实现顺序添加:" << endl << endl;
list.easyinsertbygrades(record);
cout << endl << "添加后的结果为:" << endl << endl;
list.printlist();
list.getlength();
return 0;
}
/*
测试数据
1 zhang 100 100
2 wang 99 88
3 liu 88 77
4 zhao 77 66
*/
4.运行结果:
代码效果图:
运行结果如下:
写码不易,关注一下作者再走呗o(╥﹏╥)o
谢谢支持~