1. 程式人生 > >連結串列實現模板(參考用)

連結串列實現模板(參考用)

連結串列想象成火車,火車頭看做是連結串列的表頭,車廂裡載的人和物就是元素的資料域

連線車廂的不見就是元素指標,由此,連結串列的特點是:元素之間前後依賴,串聯而成

還有,我們可以發現,連結串列的元素不能隨機訪問,在火車中行走,只能挨個走過去,而不能直接跳過去

另外,除了火車頭,每節車廂前面之連線一節車廂;除了最後的車廂。這也是連結串列的特點:

元素前面和後面不會出現多個元素相連的情況

  1. 找到連結串列中要插入的位置
  2. 令待插入結點的next指標指向插入位置的當前節點
  3. 令插入位置之前的當前節點的next指標指向待插入結點

插入需要插入在指定位置之前:

連結串列的插入分為三個階段:

  1. 頭為空:將插入的新元素標誌為頭(注意index 要等於0)
  2. 只有一個頭的連結串列:將新節點放到頭後面,同時把新節點標誌為頭
  3. 遍歷操作:index表示要插入的位置,也表示插入後新元素所在的位置

首先遍歷到要被插入元素的前一個元素,然後使新節點指向原index指點

前一個元素指向新節點

 連結串列的刪除操作:

  1. 從表頭遍歷找到要刪除的位置
  2. 令刪除位置前一個節點的next指標指向待刪除位置後一個節點
  3. 刪除節點

翻轉連結串列:

  1. 定義一個用於遍歷的指標,初始指向頭節點後一個節點
  2. 讓頭節點的next指標制空
  3. 從當前遍歷指標所指的節點開始遍歷連結串列,將遍歷到的節點next指標指向頭節點。遍歷過程中藉助另外一個指標儲存下一個遍歷到的節點
  4. 重複步驟3直至表尾,此時新連結串列就是原連結串列反轉後的連結串列
#include<iostream>
using namespace std;
// 請在下面實現結點類 Node
//一般涉及到遍歷或者刪除的操作:一般都要考慮->next

template<typename Type>
class Node {
public:
	Type data;
	Node<Type>* next;
	Node(const Type& _data) {
		data = _data;
		next = NULL;
	}
};

// 請在下面實現連結串列類 LinkedList
template<typename Type>
class LinkedList {
private:
	Node<Type>* head;
public:
	LinkedList() {
		head = NULL;
	}
	~LinkedList() {
		Node<Type>* current_node = head;  //遍歷指標
		while (current_node != NULL) {
			Node<Type>* delete_node = current_node;
			current_node = current_node->next;
			delete delete_node;
		}
	}
	//連結串列的插入
	void insert(Node<Type>* node, int index);
	void output();
	void deleteNode(int index);
	void reverse();
};

template<typename Type>
void LinkedList<Type>::reverse()   //列表的反轉操作
{
	//連結串列為空
	if (head == nullptr)
		return;

	Node<Type>* current_node = head->next;
	Node<Type>* temp_node = nullptr; //用於暫存資料
	head->next = nullptr;   //頭節點指標制空
	while (current_node != nullptr) {

		temp_node = current_node->next;
		current_node->next = head;
		head = current_node;
		current_node = temp_node;
	}
}

template<typename Type>
void LinkedList<Type>::deleteNode(int index)
{
	//兩種特殊情況的處理
	//(1)頭為空
	if (head == nullptr) {
		return;
	}
	//(2)刪除頭節點 index=0;
	if (index == 0) {
		Node<Type>* current_node = head;
		head = head->next;
		delete current_node;
	}
	//(3)正常刪除操作
	Node<Type>* current_node = head;
	int count = 0;

	//移動到前一個節點
	while (current_node->next != nullptr && count < index - 1) {
		current_node = current_node->next;
		count++;
	}
	//刪除操作
	if (count == index - 1 && current_node->next != nullptr) {
		Node<Type>* delete_node = current_node->next;
		current_node->next = delete_node->next;
		delete delete_node;
	}
}

//連結串列的遍歷
template<typename Type>
void LinkedList<Type>::output()
{
	if (head == nullptr) {
		return;
	}
	
	Node<Type>* current_node = head;
	while (current_node != nullptr) {
		cout << current_node->data << " ";
		current_node = current_node->next;
	}
	cout << endl;
}

template<typename Type>
void LinkedList<Type>::insert(Node<Type>* node, int index)
{
	//情況1 表頭為空
	if (head == nullptr) {
		if (index != 0)
			return;
		head = node;
		return;
	}
	//情況2 只存在一個表頭(插入表頭)
	if (index == 0) {
		node->next = head;   //指向head所指向的元素
		head = node;
	}
	//情況3 插入到中間
	//從頭開始遍歷
	Node<Type>* current_node = head;
	int count = 0;
	while (current_node->next != nullptr && count < index - 1) {   //遍歷到前一個元素
		current_node = current_node->next;
		count++;
	}
	if (count == index - 1) {  
		node->next = current_node->next;
		current_node->next = node;
	}
}

int main() {

	LinkedList<int> linkedlist;
	for (int i = 1; i <= 10; ++i) {
		Node<int>* node = new Node<int>(i);
		linkedlist.insert(node, i - 1);
	}

	linkedlist.output();
	linkedlist.deleteNode(3);
	linkedlist.output();
	linkedlist.reverse();
	linkedlist.output();

	system("PAUSE");
	return 0;
}