阅读建议:
一、实验目的
二、实验内容
三、实验过程
四、代码结构
五、测试结果
阅读建议:
1.实验的软硬件环境要求:
(1)硬件环境要求:PC机
(2)软件环境要求:Windows 环境下的 Microsoft Visual Studio2.该实验采用了头文件(.h)和源文件(.cpp)相结合的形式。
1. 熟练掌握单链表的存储特点;
2. 熟练掌握单链表的基本操作算法;
3. 熟练掌握面向对象程序设计方法;
4. 能灵活使用单链表解决具体的问题。
1.在主函数中定义对象,并调用成员函数,验证单链表的基本操作;
2.定义单链表类模板,例如LinkList,封装单链表的操作算法,包括:
a.创建
b.释放
c.按值查找
d.按序号查找
e.第i个位置插入和删除元素
f.求链表长度
g.输出单链表所有元素
h.原地置逆单链表
i.判断单链表是否递增
j.删除有序单链表中的值相同的多余结点(只保留一个值)
3.在主函数中定义对象,并调用成员函数,验证单链表的基本操作。
1.构造结点
using namespace std;
template
struct Node
{
T data; //数据域
Node* next; //指针域
};
2.单链表初始化---无参构造函数
template
LinkList::LinkList()
{
first = new Node;
first->next = NULL;
}
3.建立单链表---带参构造函数
template
LinkList::LinkList(T a[], int n)
{
//头插法
//first = new Node;
//first->next = NULL; //初始化空链表
//for (int i = 0; i < n; i++) {
// Node* s = NULL;
// s = new Node;
// s->data = a[i];
// s->next = first->next;
// first->next = s;
//}
//尾插法
first = new Node;
Node* r = first, * s = NULL; //尾指针初始化
for (int i = 0; i < n; i++) {
s = new Node;
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
}
4.判空,若单链表为空返回 0 ,否则返回 1。
template
int LinkList::Empty()
{
if (first->next == NULL) {
return 0;
}
else{
return 1;
}
}
5.长度,设置计数器,循环遍历单链表,返回链表长度。
template
int LinkList::Length()
{
Node* p = first->next; //工作指针初始化
int count = 0; //累加器 count 初始化
while (p!=NULL){
count++;
p = p->next;
}
return count;
}
6.遍历,设置工作指针,循环遍历单链表,逐一输出每个结点元素。
template
void LinkList::PrintList()
{
Node* p = first->next; //工作指针初始化
while (p != NULL) {
cout << p->data<<" ";
p = p->next;
}
}
7.按位查找,设置工作指针和计数器,根据传入的参数 i 循环遍历,当计数器数值等于 i 时,返回工作指针所指结点的元素。
template
T LinkList::Get(int i)
{
Node* p = first->next; //工作指针初始化
int count = 1; //累加器 count 初始化
while (p!=NULL && countnext;
count ++ ;
}
if (p == NULL) {
throw "查找位置错误!";
}else {
return p->data;
}
}
8.按值查找,设置工作指针和计数器,根据传入的参数 x 循环遍历,当工作指针所指结点的元素值等于 x 时,返回计数器的值。
template
int LinkList::Locate(T x)
{
Node* p = first->next; //工作指针初始化
int count = 1; //累加器 count 初始化
while (p!=NULL){
if (x == p->data) {
return count;
}
p = p->next;
count++;
}
throw "查找失败!";
}
9.插入操作,设置工作指针和计数器,根据传入的参数 i 和 x ,循环遍历 i 次,然后将 x 插入此位置。
template
void LinkList::Insert(int i, T x)
{
Node* p = first, * s = NULL; //工作指针初始化
int count = 0; //累加器 count 初始化
while (p!=NULL && countnext;
count++;
}
if (p == NULL) {
throw "插入位置错误!";
}
else
{
s = new Node;
s->data = x;
s->next = p->next;
p->next = s;
}
}
10.按位删除,设置工作指针和计数器,根据传入的参数 i ,循环遍历 i 次,然后将此处所指的元素删除。
template
T LinkList::Delete(int i)
{
T x;
Node* p = first, * q = NULL;
int count = 0;
while (p != NULL && count < i - 1)
{
p = p->next;
count++;
}
if (p == NULL || p->next == NULL) {
throw "删除位置错误!";
}else {
q = p->next;
x = q->data;
p->next = q->next;
delete(q);
return x;
}
}
11.置逆,设置工作指针,在循环过程中不断将结点倒接。
template
void LinkList::Reverse()
{
Node* p = first->next,* t = NULL,* q = NULL;
while (p != NULL)
{
q = p->next;
p->next = t;
t = p;
p = q;
}
first->next = t;
}
12.判断是否递增,设置工作指针,循环遍历单链表比较前后两个结点所指元素的大小,若有前者比后者大的情况则返回 false ,否则返回 true 。
template
bool LinkList::isIncreasing()
{
Node* p = first->next;
if (p == NULL) {
return true; // 链表为空,认为是递增的
}
Node* q = p->next;
while (q != NULL) {
if (p->data > q->data) {
return false;
}
p = q;
q = p->next;
}
return true;
}
13.删除重复,设置工作指针,建立双层循环,逐一比较每个结点所指元素。
template
void LinkList::removeDuplicates()
{
Node* p = first,* q,*s;
while (p != nullptr) {
s = p;
q = p->next;
while (q != nullptr) {
if (p->data == q->data) {
// 删除重复节点
s->next = q->next;
delete q; // 释放内存
q = s->next;
}else {
s = q;
q = q->next;
}
}
p = p->next;
}
}
14.销毁,设置工作指针,循环遍历整个单链表,然后逐一删除每个结点。
template
LinkList::~LinkList()
{
Node* p = first; //工作指针初始化
while (first != NULL) {
first = first->next;
delete p;
p = first;
}
}
15.主函数
int main()
{
int r[6] = { 1,5,7,8,5,5 },i,x;
//创建
LinkList L{r, 6};
//输出单链表所有元素
cout << "初始单链表元素为:";
L.PrintList();
cout << endl;
//删除有序单链表中的值相同的多余结点(只保留一个值)
cout << "删除重复元素后:";
L.removeDuplicates();
L.PrintList();
//判空
cout <> i;
if (i <= L.Length()) {
cout << "元素:" << L.Get(i) << endl;
break;
}else {
cout << "请重新输入:";
}
}
cout << "请输入需要查找序号的元素:";
while (1) {
cin >> x;
int count = 0;
for (int i=0; i < L.Length(); i++) {
if (x == r[i]) {
count++;
cout << "序号:" << L.Locate(x) << endl;
break;
}
}
if (count != 0) {
break;
}
cout << "请重新输入:";
}
//第i个位置插入元素
cout << "请输入需要插入的序号:";
cin >> i;
cout << "请输入需要插入的元素:";
cin >> x;
cout << "插入数据后单链表为:";
L.Insert(i, x);
L.PrintList();
//第i个位置删除元素
cout << endl <<"请输入需要删除的序号:";
cin >> i;
cout << "删除的元素为:" << L.Delete(i) << endl;
cout << "删除数据后单链表为:";
L.PrintList();
//判断单链表是否递增
cout << endl << "是否递增:";
if (L.isIncreasing() == false) {
cout << "否";
}else if(L.isIncreasing() == true){
cout << "是";
}
//原地置逆单链表
cout << endl << "原地置逆后:";
L.Reverse();
L.PrintList();
//判断单链表是否递增
cout << endl << "是否递增:";
if (L.isIncreasing() == false) {
cout << "否";
}
else if (L.isIncreasing() == true) {
cout << "是";
}
//释放
L.~LinkList();
cout << endl << "【已释放单链表存储空间】";
return 0;
}
完整代码链接:https://download.csdn.net/download/weixin_73286497/88758650
希望大家可以在该篇实验报告中有所收获,同时也感谢各位大佬的支持。文章如有任何问题请在评论区留言斧正,鸿蒙会尽快回复您的建议!