#pragma once
#include<iostream>
class Node
{
private:
int info;
Node* link;
public:
Node(int n=0,Node*p=NULL):info(n),link(p){}
friend class List;
};
#pragma once
#include"Node.h"
class List
{
private:
Node* head;
public:
List(int n = 0);//构造
void PrintList(); //遍历链表,进行打印
Node* Find(int data);
Node* CreatNode(int data); //创建一个结点(孤立结点)
void InsertOrder(Node* p); //按升序插入生成链表
void Insert(int n); //按位置插入生成链表(无序)
~List(); //析构函数,删除所有结点
void DeleteNode(Node* p); //删除指定结点
void MakeEmpty(); //清空一个链表,只余表头结点,包含在析构函数当中
};
#include "List.h"
#include"Node.h"
#include<iostream>
using namespace std;
List::List(int n)
{
head = new Node(n);
}
void List::PrintList()
{
Node* tempP = head->link;
cout << head->info << " Nodes: ";
while (tempP != NULL) {
cout << tempP->info << '\t';//\t的意思:补全当前字符串长度到8位
tempP = tempP->link;
}
cout << endl;
}
Node* List::Find(int data)
{
Node* tempP = head->link;
while (tempP != NULL && tempP->info != data)
tempP = tempP->link;
return tempP;
//搜索成功返回该结点地址,不成功返回NULL
}
Node* List::CreatNode(int data)
{ //建立新节点
Node* P = new Node(data);
return P;
}
void List::InsertOrder(Node* p)
{
Node* tempP = head->link, * tempQ = head;
//tempQ指向tempP前面的一个节点
while (tempP != NULL) {
if (p->info < tempP->info) break;
//找第一个比插入结点大的结点,由tempP指向
tempQ = tempP;
tempP = tempP->link;
}
p->link = tempP; //插入节点
tempQ->link = p;
head->info++; //头节点记录节点个数
}
void List::Insert(int n) //根据位置插入
{
if (head->info < n || n < 0)
{
cout << "插入位置有误!" << endl;
return;
}
Node* tempP = head; //从head开始数位置
for (int i = 0; i < n; i++)
tempP = tempP->link; //指针定位在插入节点前一个节点
cout << "输入插入节点的数据:";
int value;
cin >> value;
Node* p = new Node(value); //新建将插入节点
p->link = tempP->link; //插入
tempP->link = p;
head->info++; //头节点值域记录链表的个数
}
void List::DeleteNode(Node* p)
{
Node* tempP = head->link, * tempQ = head;
while (tempP != NULL && tempP != p)
{
tempQ = tempP;
tempP = tempP->link;
}
if (tempP) {
tempQ->link = tempP->link;
delete p;
head->info--;
}
}
void List::MakeEmpty()
{
Node* tempP;
while (head->link != NULL)
{
tempP = head->link;
head->link = tempP->link;
//把头结点后的第一个节点从链中脱离
delete tempP; //删除(释放)脱离下来的结点
head->info--; //节点个数减少
}
}
List::~List()
{
MakeEmpty();
delete head;
}
/*system("cls");清空之前的结果*/
#include "List.h"
#include "Node.h"
#include <iostream>
using namespace std;
int main() {
List pl;//创建空链表;
int num;
int n1, n2;
Node* p;
char option;
while (1)
{
cout << "\n链表操作练习:" << endl;
cout << "1: 链表中插入新节点(无序)" << endl;
cout << "2 : 链表中插入新节点(有序)" << endl;
cout << "3: 删除节点(值)" << endl;
cout << "4: 查找节点" << endl;
cout << "5: 遍历节点" << endl;
cout << "6: 清空链表" << endl;
cout << "0: 退出" << endl;
cout << "\n请输入你的选择:";
cin >> option ;
switch (option) {
case '0':
break;
case '1':
system("cls");//清空之前的结果
cout << "请输入插入节点的个数:";
cin >> n1;
while (n1) {
cout << "请输入插入节点的位置:";
cin >> n2;
pl.Insert(n2);
n1--;
}
pl.PrintList();
break;
case '2':
system("cls");
cout << "请输入插入的值:"; cin >> num;
p = pl.CreatNode(num);
pl.InsertOrder(p);
pl.PrintList();
break;
case '3':
system("cls");
cout << "请输入被删除节点值:"; cin >> num;
p = pl.Find(num);
pl.DeleteNode(p);
pl.PrintList();
break;
case '4':
system("cls");
cout << "请输入要查找的节点的值:"; cin >> num;
p = pl.Find(num);
if (p == NULL) cout << "查找失败!" << endl;
else cout << "查找成功!" << endl;
break;
case '5':
system("cls");
cout << "遍历链表所有数据:" << endl
;
pl.PrintList();
break;
case '6':
system("cls");
cout << "清空链表,只留下头节点!" << endl
;
pl.MakeEmpty();
pl.PrintList();
break;
default:
system("cls");
cout << "你输入错误,请重新输入!" << endl
;
}
if (option == '0')
break;
}
}
链表编辑学生类
method
1 改成模板类
2 typedef 修改类型名字
#pragma once
#include <iostream>
using namespace std;
class student
{
//student类型的设计”student.h”
int id;
int score;
public:
student(int i = 0, int s = 0) :id(i), score(s) { }
operator int() //类型转换函数,用于头节点的节点个数存储
{
return score;
}
student operator++(int) //头节点中存储节点个数的增加
{
score++;
return student(id, score - 1);
}
student operator--(int) //头节点中存储节点个数的减少
{
score--;
return student(id, score + 1);
}
friend ostream & operator<<(ostream & out, const student & t)
{
out << "id: " << t.id << ", score: " << t.score << endl;
return out;
} //student类型数据的插入运算符重载
friend istream& operator>>(istream& in, student& t)
{
cout << "学号id与分数score:";
in >> t.id >> t.score;
return in;
} //student类型数据的提取运算符重
};
#pragma once
#include"Node.h"
#include"student.h"
typedef student tt;
class List
{
private:
Node* head;
public:
List(tt n = 0);//构造
void PrintList(); //遍历链表,进行打印
Node* Find(tt data);
Node* CreatNode(tt data); //创建一个结点(孤立结点)
void InsertOrder(Node* p); //按升序插入生成链表
void Insert(int n); //按位置插入生成链表(无序)
~List(); //析构函数,删除所有结点
void DeleteNode(Node* p); //删除指定结点
void MakeEmpty(); //清空一个链表,只余表头结点,包含在析构函数当中
};
#include "List.h"
#include"Node.h"
#include<iostream>
using namespace std;
List::List(tt n)
{
head = new Node(n);
}
void List::PrintList()
{
Node* tempP = head->link;
cout << head->info << " Nodes: ";
while (tempP != NULL) {
cout << tempP->info << '\t';//\t的意思:补全当前字符串长度到8位
tempP = tempP->link;
}
cout << endl;
}
Node* List::Find(tt data)
{
Node* tempP = head->link;
while (tempP != NULL && tempP->info != data)
tempP = tempP->link;
return tempP;
//搜索成功返回该结点地址,不成功返回NULL
}
Node* List::CreatNode(tt data)
{ //建立新节点
Node* P = new Node(data);
return P;
}
void List::InsertOrder(Node* p)
{
Node* tempP = head->link, * tempQ = head;
//tempQ指向tempP前面的一个节点
while (tempP != NULL) {
if (p->info < tempP->info) break;
//找第一个比插入结点大的结点,由tempP指向
tempQ = tempP;
tempP = tempP->link;
}
p->link = tempP; //插入节点
tempQ->link = p;
head->info++; //头节点记录节点个数
}
void List::Insert(int n) //根据位置插入
{
if (head->info < n || n < 0)
{
cout << "插入位置有误!" << endl;
return;
}
Node* tempP = head; //从head开始数位置
for (int i = 0; i < n; i++)
tempP = tempP->link; //指针定位在插入节点前一个节点
cout << "输入插入节点的数据:";
tt value;
cin >> value;
Node* p = new Node(value); //新建将插入节点
p->link = tempP->link; //插入
tempP->link = p;
head->info++; //头节点值域记录链表的个数
}
void List::DeleteNode(Node* p)
{
Node* tempP = head->link, * tempQ = head;
while (tempP != NULL && tempP != p)
{
tempQ = tempP;
tempP = tempP->link;
}
if (tempP) {
tempQ->link = tempP->link;
delete p;
head->info--;
}
}
void List::MakeEmpty()
{
Node* tempP;
while (head->link != NULL)
{
tempP = head->link;
head->link = tempP->link;
//把头结点后的第一个节点从链中脱离
delete tempP; //删除(释放)脱离下来的结点
head->info--; //节点个数减少
}
}
List::~List()
{
MakeEmpty();
delete head;
}
#pragma once
#include<iostream>
#include"student.h"
typedef student tt;
class Node
{
private:
tt info;
Node* link;
public:
Node(tt n=0,Node*p=NULL):info(n),link(p){}
friend class List;
};
/*system("cls");清空之前的结果*/
#include "List.h"
#include "Node.h"
#include"student.h"
#include <iostream>
typedef tt student;
using namespace std;
int main() {
List pl;//创建空链表;
tt num;
int n1, n2;
Node* p;
char option;
while (1)
{
cout << "\n链表操作练习:" << endl;
cout << "1: 链表中插入新节点(无序)" << endl;
cout << "2 : 链表中插入新节点(有序)" << endl;
cout << "3: 删除节点(值)" << endl;
cout << "4: 查找节点" << endl;
cout << "5: 遍历节点" << endl;
cout << "6: 清空链表" << endl;
cout << "0: 退出" << endl;
cout << "\n请输入你的选择:";
cin >> option ;
switch (option) {
case '0':
break;
case '1':
system("cls");//清空之前的结果
cout << "请输入插入节点的个数:";
cin >> n1;
while (n1) {
cout << "请输入插入节点的位置:";
cin >> n2;
pl.Insert(n2);
n1--;
}
pl.PrintList();
break;
case '2':
system("cls");
cout << "请输入插入的值:"; cin >> num;
p = pl.CreatNode(num);
pl.InsertOrder(p);
pl.PrintList();
break;
case '3':
system("cls");
cout << "请输入被删除节点值:"; cin >> num;
p = pl.Find(num);
pl.DeleteNode(p);
pl.PrintList();
break;
case '4':
system("cls");
cout << "请输入要查找的节点的值:"; cin >> num;
p = pl.Find(num);
if (p == NULL) cout << "查找失败!" << endl;
else cout << "查找成功!" << endl;
break;
case '5':
system("cls");
cout << "遍历链表所有数据:" << endl
;
pl.PrintList();
break;
case '6':
system("cls");
cout << "清空链表,只留下头节点!" << endl
;
pl.MakeEmpty();
pl.PrintList();
break;
default:
system("cls");
cout << "你输入错误,请重新输入!" << endl
;
}
if (option == '0')
break;
}
}
拷贝构造函数
List::List(const List& tl)
{
head = new Node(0);
Node* tempP1 = tl.head->link;
Node* tempP2 = head;
while (tempP1 != NULL) {
tempP2->link = new Node(tempP1->info);
tempP1 = tempP1->link;
tempP2 = tempP2->link;
head->info++;
}
}
注意:使用时可能的报错情况
重点:在switch语句中每一个case中声明变量都是局部变量,都需要用括号括起来
解决办法:在构造时添加括号
switch (option) {
case '0':
break;
case '1':
system("cls");//清空之前的结果
cout << "请输入插入节点的个数:";
cin >> n1;
while (n1) {
cout << "请输入插入节点的位置:";
cin >> n2;
pl.Insert(n2);
n1--;
}
pl.PrintList();
{
List p2(pl);
p2.PrintList();
}//添加括号限p2的作用域只在case1当中,避免作用域在其他case中不确定而报错的情况
break;
case '2':
void pop_back(); //删除链表尾部节点
void List::pop_back()
{
head->info--;
Node* temp1=head->link;
Node* temp2 = head;
while (temp1->link!= NULL)
{
temp1 = temp1->link;
temp2 = temp2->link;
}
delete temp1;
temp2->link= NULL;//必须要两个指针,在删除之后更改倒数第二个link
}
list.cpp
#include "List.h"
#include"Node.h"
#include<iostream>
using namespace std;
List::List(int n)
{
head = new Node(n);
}
void List::PrintList()
{
Node* tempP = head->link;
cout << head->info << " Nodes: ";
while (tempP != NULL) {
cout << tempP->info << '\t';//\t的意思:补全当前字符串长度到8位
tempP = tempP->link;
}
cout << endl;
}
Node* List::Find(int data)
{
Node* tempP = head->link;
while (tempP != NULL && tempP->info != data)
tempP = tempP->link;
return tempP;
//搜索成功返回该结点地址,不成功返回NULL
}
Node* List::CreatNode(int data)
{ //建立新节点
Node* P = new Node(data);
return P;
}
void List::InsertOrder(Node* p)
{
Node* tempP = head->link, * tempQ = head;
//tempQ指向tempP前面的一个节点
while (tempP != NULL) {
if (p->info < tempP->info) break;
//找第一个比插入结点大的结点,由tempP指向
tempQ = tempP;
tempP = tempP->link;
}
p->link = tempP; //插入节点
tempQ->link = p;
head->info++; //头节点记录节点个数
}
void List::Insert(int n) //根据位置插入
{
if (head->info < n || n < 0)
{
cout << "插入位置有误!" << endl;
return;
}
Node* tempP = head; //从head开始数位置
for (int i = 0; i < n; i++)
tempP = tempP->link; //指针定位在插入节点前一个节点
cout << "输入插入节点的数据:";
int value;
cin >> value;
Node* p = new Node(value); //新建将插入节点
p->link = tempP->link; //插入
tempP->link = p;
head->info++; //头节点值域记录链表的个数
}
void List::DeleteNode(Node* p)
{
Node* tempP = head->link, * tempQ = head;
while (tempP != NULL && tempP != p)
{
tempQ = tempP;
tempP = tempP->link;
}
if (tempP) {
tempQ->link = tempP->link;
delete p;
head->info--;
}
}
void List::MakeEmpty()
{
Node* tempP;
while (head->link != NULL)
{
tempP = head->link;
head->link = tempP->link;
//把头结点后的第一个节点从链中脱离
delete tempP; //删除(释放)脱离下来的结点
head->info--; //节点个数减少
}
}
List::~List()
{
MakeEmpty();
delete head;
}
List::List(const List& tl)
{
head = new Node(0);
Node* tempP1 = tl.head->link;
Node* tempP2 = head;
while (tempP1 != NULL) {
tempP2->link = new Node(tempP1->info);
tempP1 = tempP1->link;
tempP2 = tempP2->link;
head->info++;
}
}
List& List::operator = (const List& tl)
{
if (head->info == tl.head->info)//个数相同
{
Node* temp1 = tl.head->link;
Node* temp2 = head->link;
while (temp1 != NULL)
{
temp2->info = temp1->info;
temp1 = temp1->link;
temp2 = temp2->link;
}
}
else if (head->info < tl.head->info)//个数小
{
Node* temp1 = tl.head->link;
Node* temp2 = head;
while (temp1 != NULL)
{
if (temp2->link== NULL)
{
temp2->link = new Node;
temp2 = temp2->link;
temp2->info = temp1->info;
temp1 = temp1->link;
}
else
{
temp2->info = temp1->info;
temp1 = temp1->link;
temp2 = temp2->link;
}
}
head->info = tl.head->info;
}
else if (head->info > tl.head->info)
{
Node* temp1 = tl.head->link;
Node* temp2 = head->link;
while (temp1 != NULL)
{
temp2->info = temp1->info;
temp1 = temp1->link;
temp2 = temp2->link;
}
while (temp2 != NULL)
{
Node* p = temp2;
temp2 = temp2->link;
delete p;
}
head->info = tl.head->info;
}
return (*this);
}
void List::push_back(int data)
{
Node* temp1 = head->link;
while (temp1->link != NULL)
temp1 = temp1->link;
Node* p = new Node(data);
temp1->link = p;
head->info++;
}
void List::pop_back()
{
head->info--;
Node* temp1=head->link;
Node* temp2 = head;
while (temp1->link!= NULL)
{
temp1 = temp1->link;
temp2 = temp2->link;
}
delete temp1;
temp2->link= NULL;//必须要两个指针,在删除之后更改倒数第二个link
}
Node* List::back()
{
Node* temp1=head->link;
while (temp1->link != NULL)
{
temp1 = temp1->link;
}
return temp1;
}
void List::keep(int a)
{
Node* p1 = head->link;
Node* p2 = head;
Node* m;
while (p1 != NULL)
{
if (p1->info != a)
{
p2->link = p1->link;
Node* t = p1;
p1 = p1->link;
p2 = p2->link;
delete t;
head->info--;
}
else
{
m = p1;
p1 = p1->link;
p2 = p2->link;
m->link = NULL;
}
}
}
void List::operator+=(const List& tl)
{
head->info += tl.head->info;
Node* p1 = head->link;
while (p1->link != NULL)
{
p1 = p1->link;
}
Node*q1 = (tl.head)->link;
while (q1 != NULL)
{
//Node*tt = new Node(q1->info);
p1->link = new Node(q1->info);
p1 = p1->link;
q1 = q1->link;
}
}
void List::combine(const List& tl)
{
Node*q1 = tl.head->link;
while (q1!=NULL)
{
Node* p = new Node(q1->info);
InsertOrder(p);
q1 = q1->link;
}
}
void List::reverse()
{
int all = head->info;
Node*midz;
int midi;
if (all % 2 == 0)
{
int mid=all/2;
midi = all / 2 + 1;
midz = head->link;
for(int i=1;i<midi;i++)
{
midz = midz->link;
}//找midz
//cout << midz->info << endl;
for (int i = 1; i <= midi - 1; i++)//第几次交换
{
Node* l = head->link; Node* r = midz;
for (int j = 1; j < i; j++)
{
l = l->link;
}
for (int j = 1; j <= mid - i; j++)
r = r->link;
int t = r->info;
r->info = l->info;
l->info = t;
}
}
else
{
midi = (all + 1) / 2;
midz = head->link;
for (int i = 1; i < midi; i++)
midz = midz->link;
//cout << midz->info << endl;
int ci = midi - 1;
for (int i = 1; i <= ci; i++)
{
Node*l = head->link;
Node* r = midz;
for (int j = 1; j < i; j++)
l = l->link;
for (int j = 0; j <= ci - i; j++)
r = r->link;
int t = r->info;
r->info = l->info;
l->info = t;
}
}
}
list.h
#pragma once
#include"Node.h"
#include"student.h"
//typedef student tt;
class List
{
private:
Node* head;
public:
List(int n = 0);//构造
void PrintList(); //遍历链表,进行打印
Node* Find(int data);
Node* CreatNode(int data); //创建一个结点(孤立结点)
void InsertOrder(Node* p); //按升序插入生成链表
void Insert(int n); //按位置插入生成链表(无序)
~List(); //析构函数,删除所有结点
void DeleteNode(Node* p); //删除指定结点
void MakeEmpty(); //清空一个链表,只余表头结点,包含在析构函数当中
List(const List& tl);//拷贝构造
List& operator = (const List& tl);
void push_back(int data);
void pop_back(); //删除链表尾部节点
Node* back(); //获取链表尾部指针(末节点),不删除
void keep(int a); //只保留值等于a值(要是用学生的话,a值是学生的score值)的节点
void operator+=(const List& tl); //把一个链表简单合并在链表尾部,注意tl依然是一个独立的链表
void combine(const List& tl); //两个都是有序链表, 合并后依然有序
void reverse(); //对链表进行头尾逆置
};
/*void pop_back(); //删除链表尾部节点
2) Node * back(); //获取链表尾部指针(末节点),不删除
3) void keep(int a); //只保留值等于a值(要是用学生的话,a值是学生的score值)的节点
4) void operator+=(const List & tl); //把一个链表简单合并在链表尾部,注意tl依然是一个独立的链表
5) void combine(const List & tl); //两个都是有序链表, 合并后依然有序
6) void reverse(); //对链表进行头尾逆置*/
分文件撰写注意
1)不要乱include
2)在类外定义函数最好在.cpp
文件中撰写
链表排序与交换
注意相邻情况
void List::swap(Node* l, Node* r)
{
Node* a = head;
Node* b = head;
for (; a->link != l; a = a->link);
for (; b->link != r; b = b->link);
Node* a1 = l->link;
Node* b1 = r->link;
if (b->link == a1)//相邻
{
a->link = r;
r->link = l;
l->link = b1;
return;
}
a->link = r;
r->link = a1;
b->link = l;
l->link = b1;
}
void List::mysort(int n)//升序
{
//排序:学号1 总2 平均3
switch (n)
{
case 1:
{
Node* p = head->link;
Node* p1 = head;
for (; p != NULL; p = p->link,p1=p1->link)
{
Node* min = p;
Node* q = p->link;
for (; q != NULL; q = q->link)
{
if (min->info.no > q->info.no)min = q;
}
if (min != p)
{
swap(p, min);//先后
p = p1->link;
}
}
break;
}
case 2:
{
Node* p = head->link;
Node* p1 = head;
for (; p != NULL; p = p->link,p1=p1->link)
{
Node* min = p;
Node* q = p->link;
for (; q != NULL; q = q->link)
{
if (min->info.sum > q->info.sum)min = q;
}
if (min != p)
{
swap(p, min);
p = p1->link;
}
}
break;
}
case 3:
{
Node* p = head->link;
Node* p1 = head;
for (; p != NULL; p = p->link,p1=p1->link)
{
Node* min = p;
Node* q = p->link;
for (; q != NULL; q = q->link)
{
if (min->info.average > q->info.average)min = q;
}
if (min != p)
{
swap(p, min);
p = p1->link;
}
}
break;
}
}
}