1. 程式人生 > 其它 >sql第5天 子查詢

sql第5天 子查詢

技術標籤:演算法演算法c++排序演算法快速排序

轉自:C++經典排序演算法總結

假設我們現在對“6 1 2 7 9 3 4 5 10 8”這個10個數進行排序。首先在這個序列中隨便找一個數作為基準數(不要被這個名詞嚇到了,就是一個用來參照的數,待會你就知道它用來做啥的了)。為了方便,就讓第一個數6作為基準數吧。接下來,需要將這個序列中所有比基準數大的數放在6的右邊,比基準數小的數放在6的左邊,類似下面這種排列:

3  1  2 5  4  6  9 7  10  8

在初始狀態下,數字6在序列的第1位。我們的目標是將6挪到序列中間的某個位置,假設這個位置是k。現在就需要尋找這個k,並且以第k位為分界點,左邊的數都小於等於6,右邊的數都大於等於6,遞迴對左右兩個區間進行同樣排序即可。想一想,你有辦法可以做到這點嗎?這就是快速排序所解決的問題。

快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,通常稱其為分治法(Divide-and-ConquerMethod)。它的平均時間複雜度為O(nlogn),最壞時間複雜度為O(n^2).

首先上圖:

從圖中我們可以看到:

left指標,right指標,base參照數。

其實思想是蠻簡單的,就是通過第一遍的遍歷(讓left和right指標重合)來找到陣列的切割點。

第一步:首先我們從陣列的left位置取出該數(20)作為基準(base)參照物。(如果是選取隨機的,則找到隨機的哨兵之後,將它與第一個元素交換,開始普通的快排)

第二步:從陣列的right位置向前找,一直找到比(base)小的數,如果找到,將此數賦給left位置(也就是將10賦給20),此時陣列為:10,40,50,10,60,left和right指標分別為前後的10。

第三步:從陣列的left位置向後找,一直找到比(base)大的數,如果找到,將此數賦給right的位置(也就是40賦給10),此時陣列為:10,40,50,40,60,left和right指標分別為前後的40。

第四步:重複“第二,第三“步驟,直到left和right指標重合,最後將(base)放到40的位置,此時陣列值為: 10,20,50,40,60,至此完成一次排序。

第五步:此時20已經潛入到陣列的內部,20的左側一組數都比20小,20的右側作為一組數都比20大,以20為切入點對左右兩邊數按照"第一,第二,第三,第四"步驟進行,最終快排大功告成。

快速排序程式碼如下

#include<iostream>
#include<algorithm>
#include<ctime>

using namespace std;

void OutNum(int *nNum, size_t len)
{
	for (size_t i = 0; i < len; i++)
		cout << nNum[i] << ' ';
	cout << endl;
}

void QuickSort(int* nNum, int nLeft, int nRight)
{
	//處理異常資料
	if (NULL == nNum || nLeft < 0 || nRight < 0)
		return;

	// 遞迴結束條件
	if (nLeft >= nRight)
		return;

	//防止有序佇列導致快速排序效率降低 
	srand((unsigned)time(NULL));
	int nLen = nRight - nLeft;
	int nKeyIndex = rand() % (nLen + 1) + nLeft;
	swap(nNum[nLeft], nNum[nKeyIndex]);

	int nBase = nNum[nLeft];
	int nFlagLeft = nLeft;
	int nFalgRight = nRight;

	while (nFlagLeft < nFalgRight)
	{
		// 從後往前找,第一個比基準小的數
		while (nFlagLeft < nFalgRight && nNum[nFalgRight] >= nBase) {
			nFalgRight--;
		}
		if (nFlagLeft < nFalgRight) {
			nNum[nFlagLeft] = nNum[nFalgRight];
		}

		// 從前往後找,第一個比基準大的數
		while (nFlagLeft < nFalgRight && nNum[nFlagLeft] <= nBase) {
			nFlagLeft++;
		}
		if (nFlagLeft < nFalgRight) {
			nNum[nFalgRight] = nNum[nFlagLeft];
		}
	}
	nNum[nFlagLeft] = nBase;

	// 遞迴呼叫
	QuickSort(nNum, nLeft, nFlagLeft - 1);
	QuickSort(nNum, nFalgRight + 1, nRight);

}

int main()
{
	//int nNum[10] = {1,7,4,5,3,8,6,9,0,2};
	//int nNum[10] = { 0,1,2,3,4,5,6,7,8,9 };
	//int nNum[10] = { 0,1,2,3,4,5,6,7,9,8 };
	int nNum[20] = { 20,40,50,10,60, 1,7,4,5,3 };

	QuickSort(nNum, 0, 9);

	OutNum(nNum, 10);
	return 0;
}