#include <iostream> #include <stdlib.h> #include <time.h> #include <fstream> #include <string> using namespace std; //类 class List { public: //构造器初始化,生成头节点 List() { head = new Node; head->next = NULL; } //成员函数 void createList(); void insertList(int data); void travelList(int chance); void input(); int addNode(); void deleteData(int addNum); void ifClear(); void clearList(); //重载下标 int operator[](int idx); //重载+ friend List operator+(List& List_1, List& List_2); //重载- friend List operator-(List& List_1, List& List_2); //重载<< friend ostream& operator<<(ostream& os, List& list); //重载>> friend istream& operator>>(istream& is, List& list); //冒泡排序 void bubbleSortList(List& list); private: //数据成员 struct Node { int data; //数据域 struct Node* next; //指针域 } *head;//头指针 int num;//链表元素个数 }; //头插法生成节点 void List::insertList(int data) { Node* cur = new Node; //插入数据 cur->data = data; //插入节点 cur->next = head->next; head->next = cur; } //调用insertList输入数据,生成链表 void List::input() { cout << "请输入链表数量长度:"; cin >> num; srand(time(NULL)); for (int i = 0; i < num; i++) { insertList(rand() % 100); } } //任意位置插入节点 int List::addNode() { int d, idx; cout << "请输入你要插入的节点数据:"; cin >> d; cout << "请输入你要插入的节点位置: "; cin >> idx; Node* tp = NULL; Node* link = head; //寻找插入位置 if (idx<1 || idx>num + 1) { cout << "操作非法" << endl; return num; } else { for (int i = 0; i < idx; i++) { tp = link; link = link->next; } Node* cur = new Node; tp->next = cur; cur->data = d; cur->next = link; travelList(1); return ++num; } } ofstream mycout1("D:/text1.txt"); ofstream mycout2("D:/text2.txt"); //遍历链表并将数据存入文件 void List::travelList(int chance) { Node* temp = head->next; //防止头指针地址改变 while (temp != NULL) { cout << temp->data << " "; if (chance == 1) mycout1 << temp->data << " "; else mycout2 << temp->data << " "; temp = temp->next; } cout << endl; } //删除节点 void List::deleteData(int addNum) { int i, j = 0; cout << "请问您要删除第几个数据: "; cin >> i; Node* tp = NULL; Node* link = head;//link为删除节点后面的一个节点,temp为删除节点 if (addNum < i || i < 0) cout << "操作非法!!" << endl; else { while (link->next) { tp = link->next; //第一个节点 j++; if (i == j) //找的删除的节点 { link->next = tp->next; delete tp; break; } link = link->next; } travelList(1); } } //清空链表 void List::clearList() { Node* tp = NULL; Node* ph = head->next; while (head->next) { tp = ph; ph = ph->next; delete tp; head->next = ph; } travelList(1); cout << endl; } //询问是否清空 void List::ifClear() { string i; if (!head->next) { cout << "链表已清空!!!" << endl; } else { cout << "是否清空链表(是/否):"; cin >> i; if (i == "是") { clearList(); cout << "链表清空完成!!!" << endl; } else cout << "链表未清空!!!" << endl; } } //冒泡排序 void List::bubbleSortList(List& list) { //求list链表长度len int len=0; //临时指针phead Node* phead = list.head->next; while (phead) { len++; phead = phead->next; } //冒泡排序 for (int i=0;i<len-1; i++) { //phead指向头结点 phead = list.head; //ph1指向首元结点 Node* ph1 = phead->next; //ph2指向首元结点的后继 Node* ph2 = ph1->next; //进入循环冒出最大的数 for (int j = 0; j < len - 1 - i; j++) { //如果前面的值大于后面的值则交换 if (ph1->data > ph2->data) { phead->next = ph2; ph1->next = ph2->next; ph2->next = ph1; //结点交换后,ph1与ph2位置颠倒回来 Node* temp = ph1; ph1 = ph2; ph2 = temp; } //如果不需要交换,三指针移动 phead = phead->next; ph1 = ph1->next; ph2 = ph2->next; } } //打印结点数据 phead = list.head->next; while (phead) { cout << phead->data << " "; phead = phead->next; } cout << endl; } //下标重载 int List::operator[](int idx) { //临时指针temp,为了防止头指针改变 Node* temp = head; //如果下标小于链表长度进行取值 if (idx < num) { for (int i = 0; i < idx; i++) { temp = temp->next; } } return temp->data; } //+ 重载 List operator +(List & List_1, List & List_2) { //由链表1生成链表3 List List_3; //生成临时指针temp_1 List::Node* temp_1 = List_1.head->next; //把链表1的值给链表3 while (temp_1) { List_3.insertList(temp_1->data); temp_1 = temp_1->next; } //生成临时指针temp_2 List::Node* temp_2 = List_2.head->next; //把链表2的值给链表3 while (temp_2) { List_3.insertList(temp_2->data); temp_2 = temp_2->next; } return List_3; } //- 重载 List operator -(List & List_1, List & List_2) { //生成链表4 List List_4; //生成临时指针temp_1,temp_2 List::Node* temp_1 = List_1.head->next; List::Node* temp_2 = List_2.head->next; //flag为1链表2有链表1的值,为0则没有 int flag = 0; //比较链表一和链表二,不等就将数据存入List_4 while (temp_1) { //临时指针temp_2回溯 temp_2 = List_2.head->next; while (temp_2) { //判断是否有相同值 if (temp_1->data == temp_2->data) { flag = 1; break; } //指针移动 temp_2 = temp_2->next; } //没有相同值List_4则插入数据 if (!flag) { List_4.insertList(temp_1->data); } //指针移动,开始下一轮对比 temp_1 = temp_1->next; flag = 0; } return List_4; } //重载<< ostream& operator<<(ostream & os, List & list) { list.bubbleSortList(list); return os; } //重载>> istream &operator>>(istream & is, List & list) { int size, i=0; cout << "(输入链表长度):"; is >> size; //当i<size时录入数据 while (i < size) { int data; is >> data; //插入数据 list.insertList(data); i++; } return is; } int main() { //初始化,生成List_1 List List_1; //输入链表长度 List_1.input(); //遍历链表,并存入text1文件 List_1.travelList(1); //添加节点并返回总结点数 int addNum = List_1.addNode(); //删除节点 List_1.deleteData(addNum); //初始化,生成List_2 List List_2; //输入链表长度 List_2.input(); //遍历链表,并存入text2文件 List_2.travelList(2); //重载下标 cout << "取链表2的第二个元素:"; cout << List_2[2]<<endl; //重载+ List List_3; List_3 = List_1 + List_2; cout << "两链表+为:"; List_3.bubbleSortList(List_3); //重载- List List_4; List_4 = List_1 - List_2; cout << "两链表-为:"; List_4.bubbleSortList(List_4); //重载<< cout << "cout<<List_4:"; cout << List_4 << endl; //重载>> List List_5; cout << "cin>>List_5"; cin >> List_5; cout << "链表List_5: " << List_5; //询问是否清空链表1 List_1.ifClear(); //关闭打开的文件 mycout1.close(); mycout2.close(); return 0; }
用类创建单链表时,可以将结构体封装为私有成员,在构造函数中初始化链表极为方便;链表的删除操作需要先进行遍历,并且遍历途中不能随意改变头结点的位置,所以在进行链表的操作时,皆需要临时变量防止头指针改变;除此之外,在进行冒泡排序时,需要画图理清逻辑,虽然比较过后,链表的连接方式改变了,但是ph1与ph2位置颠倒,需要互换回来,使下一次比较正常运行;运算符“+”号重载时,如果直接由链表1生成链表3,在进行减操作时,会发现链表1随链表3的改变而改变了,导致在进行“-”操作时出错,后在“+”操作时,对链表3进行逐一赋值,问题得到解决。总的来说,此次试验对友元函数和运算符重载有了新的收获,例如如果将”<<”重载,”<<”会根据你输出的内容来调用相应的函数,从而在使用cout时更为方便。