常用排序算法(一)插入排序、希爾排序、冒泡排序
常用排序算法(三)歸併排序、堆排序、基數排序
1 選擇排序
選擇排序也是一種簡單直觀的排序算法。它的工作原理很容易理解:初始時在序列中找到最小(大)元素,放到序列的起始位置作爲已排序序列;然後,再從剩餘未排序元素中繼續尋找最小(大)元素,放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。算法平均時間複雜度O(n2)。
一種用C++實現的選擇排序算法如下:
void SelectSort(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])
{
int min = a[j];
a[j] = a[i];
a[i] = min;
}
}
}
}
上面示例代碼中,第二層循環需要找出從下標 i 開始的最小值,對於每一個比a[i]小的值a[j]都進行交換,下面進行改進:
void SelectSort(int a[],int n) //選擇排序
{
int mix,temp;
for(int i=0;i<n-1;i++) //每次循環數組,找出最小的元素,放在前面,前面的即爲排序好的
{
mix=i; //假設最小元素的下標
for(int j=i+1;j<n;j++) //將上面假設的最小元素與數組比較,交換出最小的元素的下標
if(a[j]<a[mix])
mix=j;
//若數組中真的有比假設的元素還小,就交換
if(i!=mix)
{
temp=a[i];
a[i]=a[mix];
a[mix]=temp;
}
}
}
改進後的代碼,內層循環只進行判斷,並記錄下最小值的下標,然後在外層循環只需交換一次數據,稍微加快了速度。
注意選擇排序與冒泡排序的區別:冒泡排序通過依次交換相鄰兩個順序不合法的元素位置,從而將當前最小(大)元素放到合適的位置;而選擇排序每遍歷一次都記住了當前最小(大)元素的位置,最後僅需一次交換操作即可將其放到合適的位置。
2 快速排序
-
基本思想:(分治)
- 先從數列中取出一個數作爲key值;
- 將比這個數小的數全部放在它的左邊,大於或等於它的數全部放在它的右邊;
- 對左右兩個小數列重複第二步,直至各區間只有1個數。
-
輔助理解:挖坑填數
- 初始時 i = 0; j = 9; key=72
由於已經將a[0]中的數保存到key中,可以理解成在數組a[0]上挖了個坑,可以將其它數據填充到這來。
從j開始向前找一個比key小的數。當j=8,符合條件,a[0] = a[8] ; i++ ; 將a[8]挖出再填到上一個坑a[0]中。
這樣一個坑a[0]就被搞定了,但又形成了一個新坑a[8],這怎麼辦了?簡單,再找數字來填a[8]這個坑。
這次從i開始向後找一個大於key的數,當i=3,符合條件,a[8] = a[3] ; j-- ; 將a[3]挖出再填到上一個坑中。數組:72 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 48 - 85 0 1 2 3 4 5 6 7 8 9
- 此時 i = 3; j = 7; key=72
再重複上面的步驟,先從後向前找,再從前向後找。
從j開始向前找,當j=5,符合條件,將a[5]挖出填到上一個坑中,a[3] = a[5]; i++;
從i開始向後找,當i=5時,由於i==j退出。
此時,i = j = 5,而a[5]剛好又是上次挖的坑,因此將key填入a[5]。數組:48 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 88 - 85 0 1 2 3 4 5 6 7 8 9
- 可以看出a[5]前面的數字都小於它,a[5]後面的數字都大於它。因此再對a[0…4]和a[6…9]這二個子區間重複上述步驟就可以了。
<數組:48 - 6 - 57 - 42 - 60 - 72 - 83 - 73 - 88 - 85 0 1 2 3 4 5 6 7 8 9
- 初始時 i = 0; j = 9; key=72
平均時間複雜度:O(N*logN)
void QuickSort(int a[], int l, int r) {
if (l >= r)
return;
int i = l; int j = r; int key = a[l];//選擇第一個數爲key
while (i<j) {
while (i<j && a[j] >= key)//從右向左找第一個小於key的值
j--;
if (i<j) {
a[i] = a[j];
i++;
}
while (i<j && a[i]<key)//從左向右找第一個大於key的值
i++;
if (i<j) {
a[j] = a[i];
j--;
}
}
a[i] = key;
QuickSort(a, l, i - 1);//遞歸調用
QuickSort(a, i + 1, r);//遞歸調用
}