#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時更為方便。