c++單鏈表冒泡排序(交換結點),鏈表增刪改查,運算符重載


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM