[C++]歸併排序(連結串列描述)

mzman發表於2020-12-14

基本思想

分而治之:通過遞迴把一個無序連結串列對半分成許多小連結串列,然後對這些小連結串列兩兩之間進行歸併(合併有序連結串列),從而最終使整個連結串列有序。

程式碼

#include<iostream>
using namespace std;
template<class T>
struct chainNode//定義連結串列節點
{
	T element;
	chainNode<T>* next;
	
	chainNode(const T& theElement)
	{
		next = nullptr;
		element = theElement;
	}
	chainNode(const T& theElement, chainNode<T>* theNext)
	{
		next = theNext;
		element = theElement;
	}
};
template<class T>
class chain
{
public:
	chain()
	{
		first = nullptr;
		size = 0;
	}
	void push(const T& theElement)//只提供頭插法
	{
		first = new chainNode<T>(theElement, first);
		size++;
	}
	void mergeSort() { first = mergeSort(first); }
	void print()
	{
		chainNode<T>* currentNode = first;
		while (currentNode != nullptr)
		{
			cout << currentNode->element << " ";
			currentNode = currentNode->next;
		}
		cout << endl;
	}
private:
	chainNode<T>* first;
	int size;
	chainNode<T>* merge(chainNode<T>* head1, chainNode<T>* head2)//合併兩個有序連結串列實現歸併
	{
		chainNode<T> top(0);//合併連結串列的頭節點,不參與返回
		chainNode<T>* currentNode = &top;
		while (head1 != nullptr && head2 != nullptr)//將兩連結串列中較小的一個節點加入到合併連結串列中,直到其中一個連結串列到達結尾
		{
			if (head1->element < head2->element)
			{
				currentNode->next = head1;
				head1 = head1->next;
			}
			else
			{
				currentNode->next = head2;
				head2 = head2->next;
			}
			currentNode = currentNode->next;
		}
		//之後把未到達結尾的連結串列加入到合併連結串列中
		if (head1 != nullptr)
			currentNode->next = head1;
		if (head2 != nullptr)
			currentNode->next = head2;
		return top.next;
	}
	chainNode<T>* mergeSort(chainNode<T>* theFirst)
	{
		if (theFirst == nullptr || theFirst->next == nullptr)
			return theFirst;
		chainNode<T>* fastNode = theFirst;
		chainNode<T>* slowNode = theFirst;
		while (fastNode->next != nullptr&& fastNode->next->next != nullptr)//當快節點到達結尾時,慢節點正好到達連結串列中間
		{
			slowNode = slowNode->next;
			fastNode = fastNode->next->next;
		}
		chainNode<T>* head2 = slowNode->next;//head2是後半段連結串列的頭節點
		slowNode->next = nullptr;//刪除後半段
		chainNode<T>* head1 = theFirst;//head1是前半段連結串列的頭節點
		head1 = mergeSort(head1);
		head2 = mergeSort(head2);
		return merge(head1, head2);//返回兩段有序連結串列歸併之後的連結串列
	}
};
int main()
{
	int n,num;
	cin >> n;//n表示連結串列節點個數
	chain<int> c;
	for (int i = 0; i < n; i++)
	{
		cin >> num;
		c.push(num);
	}
	c.mergeSort();
	c.print();
}

相關文章