原始地址:C / C++演算法學習筆記(5)-選擇法
選擇法:
現在我們終於可以看到一點希望:選擇法,這種方法提高了一點效能(某些情況下)這種方法類似我們人為的排序習慣:
從資料中選擇最小的同第一個值交換,在從省下的部分中選擇最小的與第二個交換,這樣往複下去。
#include <iostream.h>void SelectSort(int* pData,int Count){ int iTemp; int iPos; for(int i=0;i<Count-1;i++) { iTemp = pData[i]; iPos = i; for(int j=i+1;j<Count;j++) { if(pData[j]<iTemp) { iTemp = pData[j]; iPos = j; } } pData[iPos] = pData[i]; pData[i] = iTemp; }} void main(){ int data[] = {10,9,8,7,6,5,4}; SelectSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"/n";}該排序法的圖示如下; i=0時: iTemp = pData[0]=10;iPos = i=0; j=1 ; pData[j]<iTemp ---> pData[1]=9<10; iTemp=pData[1]=9; ipos=j=1; j++=2 j=2; pData[j]<iTemp----> pData[2]=8<9; iTemp=pData[2]=8; ipos=j=2; j++=3 . . . j=6; pData[j]<iTemp----> pData[6]=4<5; iTemp=pData[6]=4; ipos=j=6; j++=7; pData[6]=Pdata[0]; pData[0]=4;
比較前 | 第一次 | 第二次 | 第三次
10 4 4 4
9 9 5 5
8 8 8 6
7 7 7 7
6 6 6 8
5 5 9 9
4 10 10 10
由上面可以看到選擇排序法並沒有在一開始就交換資料,而是用第一個資料去和所有的資料比較,
如果第一個資料小於第二個資料,那麼,先把第二個資料放到一個臨時變數裡面,同時記錄這個較小
的資料在待排序的集合中的位置。再用該集合中的下一個資料和我們之前放在臨時變數中的資料比較。
也就是我們目前認為最小的資料比較,如果比我們之前選出來的資料小,那麼再替換該變數。如果比這個
資料大,則繼續用下一個資料來比較。知道所有的資料都比較完為止。到這時,臨時變數裡面訪的就是
最小的資料了。我們把這個資料和第一個資料做對換。此時,最小的元素排到了第一位。
倒序(最糟情況)
第一輪:10,9,8,7->(iTemp=9)10,9,8,7->(iTemp=8)10,9,8,7->(iTemp=7)7,9,8,10(交換1次)
第二輪:7,9,8,10->7,9,8,10(iTemp=8)->(iTemp=8)7,8,9,10(交換1次)
第一輪:7,8,9,10->(iTemp=9)7,8,9,10(交換0次)
迴圈次數:6次
交換次數:2次
其他:
第一輪:8,10,7,9->(iTemp=8)8,10,7,9->(iTemp=7)8,10,7,9->(iTemp=7)7,10,8,9(交換1次)
第二輪:7,10,8,9->(iTemp=8)7,10,8,9->(iTemp=8)7,8,10,9(交換1次)
第一輪:7,8,10,9->(iTemp=9)7,8,9,10(交換1次)
迴圈次數:6次
交換次數:3次
遺憾的是演算法需要的迴圈次數依然是1/2*(n-1)*n。所以演算法複雜度為O(n*n)。
我們來看他的交換。由於每次外層迴圈只產生一次交換(只有一個最小值)。所以f(n)<=n
所以我們有f(n)=O(n)。所以,在資料較亂的時候,可以減少一定的交換次數。