資料結構之連結串列操作

*live_it_up發表於2020-10-24

帶頭結點的雙向迴圈連結串列的基本操作

前言

連結串列是線性表的一種實現形式,它的核心是指標,主要特點是增加與刪除不需要移動大量元素,查詢某一特定元素較慢,邏輯上相鄰的元素物理上不一定相鄰。
連結串列主要分為單連結串列,雙向連結串列與迴圈連結串列。每種連結串列又可分為帶頭結點的和不帶頭結點的。本篇主要介紹帶頭結點的雙向迴圈連結串列的基本操作。

操作說明

Define

雙向迴圈連結串列的每個結點需要有兩個指標,一個指向前驅,一個指向後繼。

//定義程式碼示例
class Node
{
public:
	int  data;
	Node* next;
	Node* prior;
public:
	Node()                //建構函式初始化指標資料成員
	{
		next = nullptr;  
		prior = nullptr;
		data = -1;
	}
};

Creat

建立雙向迴圈連結串列時需要注意保證每個結點的兩個指標都被賦值,且首元素的前驅指標指向尾元素,尾元素的後繼指標指向首元素。

//建立程式碼示例
void Fill(Node *&A)
{   //輸入長度
	int N;
	cin >> N;
	//插入頭結點
	Node* p;
	p = new Node;
	p->prior = p;
	p->next = p;
	A = p;
	Node* temp = A;
	for (int i = 0; i < N; i++)
	{
		Node* p;
		p = new Node;
		p->data = rand();       //隨機生成資料
		temp->next = p;
		A->prior = p;
		p->prior = temp;
		p->next = A;
		temp = temp->next;
	}
}

Insert

插入操作時需要首先判斷連結串列是否為空,插入位置是否超出連結串列,同時需要注意指標操作的順序,要“先連線再剪線”。

//插入程式碼示例
bool Insert(Node* A)
{   
	if (A->next==A)
		return false;  //判斷是否為空
	int place;
	cin >> place;
	Node* temp = A;
	int length = 0;  
	while (temp->next != A)
	{
		temp = temp->next;
		++length;
	}
	if (place > length)
		return false;    //判斷是否超出長度
	Node* p;
	p = new Node;
	p->data = 0;               //插入值為0
	for (int i = 0; i < place - 1; i++)
		A = A->next;                     //找到插入位置
	p->next = A->next;
	p->prior = A;
	A->next->prior = p;
	A->next = p;
	return true;
}

Delete

刪除操作與插入操作類似,但是最後需要delete掉對應結點以釋放記憶體。

//刪除程式碼示例
bool Delete(Node* A)
{
	if (A->next==A)
		return false;  //判斷是否為空
	int place;
	cin >> place;

	Node* temp = A;
	int length = 0;
	while (temp->next != A)
	{
		temp = temp->next;
		++length;
	}
	if (place > length)
		return false;             //判斷是否超出長度
	for (int i = 0; i < place; i++)
		A = A->next;
	A->next->prior = A->prior;     //指標操作
	A->prior->next = A->next;
	delete A;                 //釋放記憶體
	return true;
}

Inverse

轉置操作定義兩個指標,一個指向頭,一個指向尾,兩指標同時向中間移動並交換資料,兩指標“相遇”時停止移動,此處需注意“相遇”的判斷。

//轉置程式碼示例
bool Inverse(Node*& A)
{
	if (A->next==A)
		return false;  //判斷是否為空
	Node* Bejin = A->next; 
	Node* Last = A->prior;       //指標賦值
	int n;
	while (Last->next!=Bejin&&Last!=Bejin)    //"相遇"時停止
	{
		n = Last->data;
		Last->data = Bejin->data;
		Bejin->data = n;
		Last = Last->prior;
		Bejin = Bejin->next;
	}
	return true;
}

Output

輸出函式需注意中止條件的判斷,避免重複迴圈輸出。

//輸出程式碼示例
bool Output(Node* List)
{
	if (List->next == List)
		return false;         //判斷是否為空
	Node* temp = List;
	temp = temp->next;
	while (temp != List)            //中止判斷
	{
		cout << temp->data << ",";
		temp = temp->next;
	}
	cout << "\n";
}

執行展示

主函式

依次實現建立,插入,刪除,轉置操作,並在每次操作完成後輸出連結串列。最後釋放記憶體。

int main()
{
	srand(time(0));
	Node* List;
	List = new Node;
	Fill(List);
	Output(List);
	Insert(List);
	Output(List);
	Delete(List);
	Output(List);
	Inverse(List);
	Output(List);
	Node* test1 = List->prior;   //清空記憶體
	while (List != test1)
	{
		Node* temp = List->next;
		delete List;
		List = temp;
	}
	delete List;
	return 0;
}

結果

在這裡插入圖片描述

相關文章