排序算法

關鍵詞:插入冒泡選擇、希爾歸併快排、堆排序


倒着講

1.堆排序

1.1有關堆與優先隊列,看這裏堆與優先隊列

1.2堆排序的思想:

    最大堆,每次把根從堆中取出來刪去,然後從新建堆,並把取出來的元素放到數組的最後

    那麼最大的元素被放到n-1的位置,第二大的元素被放到n-2的位置。。。直到最後,數組就變成的由小到大的順序

 1.3算法複雜度

     最好最差平均都是O(nlogn)

1.4核心代碼

void heapsort(int A[], int n)
{
	int maxval;
	Heap H(A, n, n);
	for (int i = 0; i < n; i++)
		maxval = H.removefirst();
}

2.快速排序

2.1快排的思想:
快排的思想可以由BST得來,在BST中,左子樹的值都小於根節點,右子樹的值都大於等於根節點,因此檢索的時候很快很方便。但問題在於二叉樹空間佔用太大,而且很容易變得不平衡。

因此,產生了快排的思想:
引入一個軸值pivot,這個值類似於BST中的根節點。把數組中小與pivot的值放到pivot的左邊,而大於等於pivot的值放到其右邊。在利用該思想,分別對軸值左邊的部分和右邊的部分排序。直到左邊和右邊的長度<=1.

具體實現的時候,由於不知道有多少個元素比軸值大,多少個元素比軸值小
因此每次把軸值先交換的最後,然後用兩個指針,一個從左往右,一個從右往左,如果遇到左邊指針指向的值大於軸值,右邊指向的值小與軸值,交換兩個元素,直到左右指針相遇,就是軸值應該在的位置,在把軸值換回來。

2.2實現代碼(代碼經過測試)
int findPivot(int A[], int i, int j)
{
	return (i + j) / 2;
}

int partition(int A[], int l, int r, int p)
{
	do {
		while (A[++l] < p);
		while (l<r&&A[--r]>p);
		swap(A, l, r);
	} while (l < r);

	return l;
}
void qsort(int A[], int i, int j)
{
	if (j<=i)return;
	int index = findPivot(A, i, j);
	swap(A, index, j);
	int k = partition(A, i - 1, j, A[j]);
	swap(A, k, j);

	qsort(A, i, k - 1);
	qsort(A, k + 1, j);
}

3.歸併排序

3.1思想;
分治的思想。把原數組分成兩個子數組,對子數組排序,然後在把兩個數組合並起來。
其實該算法的關鍵就在合併上:把兩個已經有序的數組合併成一個有序的數組

實現思想就是用兩個指針分別指向這兩個數組的開頭,然後比較兩指針指向的值,選着合適的放入要合併的新數組中並且將指針後移。

3.2實現代碼(經過測試)
void mergeSort(int A[], int temp[], int left, int right)
{
	if (left == right)return;
	int mid = (left + right) / 2;
	mergeSort(A, temp, left, mid);
	mergeSort(A, temp, mid + 1, right);

	for (int i = left; i <= right; i++)
		temp[i] = A[i];

	int i1 = left, i2 = mid + 1;
	for (int curr=left;curr<=right;curr++)
	{
		if (i1 == mid + 1)
			A[curr] = temp[i2++];
		else if (i2 > right)
			A[curr] = temp[i1++];
		else if (temp[i1] < temp[i2])
			A[curr] = temp[i1++];
		else
			A[curr] = temp[i2++];
	}


}



4.希爾排序

4.1思想:
希爾排序可以看做是對插入排序的優化。因爲插入排序對於基本有序的序列很快,並且比較適用於長度比較小的序列。
由以上兩個特點,得出希爾排序的思想:
把大序列分成小序列,對小序列插入排序,使整個大序列儘可能的變得基本有序。

4.2代碼(經過測試)
//按從小到大排序
void insort(int A[], int n, int incr)
{
	for (int i = incr; i < n; i += incr)
		for (int j = i; j >= incr && (A[j - incr] > A[j]); j -= incr)
			swap(A, j - incr, j);
}

void shellsort(int A[], int n)
{
	for (int i = n / 2; i>2; i /= 2)
		for (int j = i; j >= 0; j--)
		{
			insort(&A[j], n - j, i);
		}
	insort(A, n, 1);
}


5.插入、冒泡、選擇排序

5.1插入排序
思想:把新的元素與前面已經排好序的子序列進行比較,插入到合適的位置
代碼:把4.2中,insort函數incr置成1,就是插入排序的代碼

5.2冒泡排序
思想:每一次最小的元素就像氣泡一樣冒到數組的最前面
代碼:
void bublesort(int A[], int n)
{
	for (int i = 0; i < n - 1; i++)
		for (int j = i+1; j < n; j++)
			if (A[j] < A[i])
				swap(A, i, j);
}

5.3選擇
思想:選擇排序是對冒泡排序的一種優化,每次記住最小元素的位置,到最後再進行交換
代碼:
void selectSort(int A[], int n)
{
	for (int i = 0; i < n; i++)
	{
		int min = i;
		for (int j = n - 1; j > i; j--)
		{
			if (A[j] < A[min])
				min = j;
		}
		swap(A, i, min);
	}	
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章