1.直接排序
思想:遍歷數組元素,找到其中最小(大)元素,將其放在數組起始位置,再從剩餘數組元素中繼續尋找最小(大)元素,放在已排序序列末尾,重複至整條序列有序。
代碼實現:
void select_sort(int* arr,int len)
{
if(arr == NULL || len<0)
return ;
int min = arr[0];
int min_index = 0;
for(int i=0;i<len-1;i++)
{
min = arr[i];
min_idex = i;
for(int j=0;j<len;j++)
{
if(min > arr[j])
{
min = arr[j];
min_index = j;
}
}
//交換最值與當前無序序列首元素位置
if(i != min_index)
{
int temp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = temp;
}
}
}
優點:一輪比較只需要換一次位置,
缺點:效率慢,不穩定。
2.堆排序
基礎:該排序方法基於“堆”的數據結構,而“堆”的本質是一個有序排列的完全二叉樹,按照父節點鍵值與子節點鍵值的大小關係分爲大根堆和小根堆。
思想:首先構建大根堆,將該數組(a1,a2……an)命名爲無序區,然後將最大元素(a1)與無序區最後一個元素(an)進行位置互換,得到新的有序區(an)和無序區(a1,a2……an-1),且滿足a[1,2…n-1]<=a[n],然後繼續調整無序區成爲新堆,重複以上算法,得到新的有序區與無序區,直到有序區的元素個數爲n-1,則整個排序過程完成。
代碼實現:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
//堆調整算法
void HeapAdjust(int num[],int i,int length) {
//定義max保存以num[i]爲根的最小堆中最大值的下標,初始值爲i
int max=i;
//判斷num[i]是否爲根結點 (下標i<=length/2-1的結點都是根節點)
if(i<=length/2-1) {
//判斷num[2*i+1]是否在堆內,若在,判斷其是否大於num[max],若大於,將其下標2*i+1賦予給max
if((2*i+1)<length && num[2*i+1]>num[max]) {
max=2*i+1;
}
//判斷num[2*(i+1)]是否在堆內,若在,判斷其是否大於num[max],若大於,將其下標2*(i+1)賦予給max
if((2*(i+1))<length && num[2*(i+1)]>num[max]) {
max=2*(i+1);
}
//若i不等於max,則說明以num[i]爲根的最小堆中num[max]是最大值,將num[max]與根結點num[i]交換位置
if(i!=max) {
num[i]=num[i]^num[max];
num[max]=num[i]^num[max];
num[i]=num[i]^num[max];
//交換後,爲防止以num[max]爲根結點的最小堆結構發生變換,再次調用堆調整算法
HeapAdjust(num,max,length);
}
}
}
//堆排序算法
void HeapSort(int num[],int length) {
int i;
//找到最後一個非葉子結點,先從最後一個非葉子結點組成的最小堆進行堆調整
for(i=length/2-1;i>=0;i--) //調用調整堆算法將數組從下往上調整爲大根堆
HeapAdjust(num,i,length);
for(i=length-1;i>0;i--) {
//將數組第一個數和最後一個數換位置
num[i]=num[i]^num[0];
num[0]=num[i]^num[0];
num[i]=num[i]^num[0];
//繼續調用調整堆算法,將剩餘數據組成的堆從上往下調整爲大根堆
HeapAdjust(num,0,i);
}
}
int main() {
int i;
int num[]={8,5,7,12,48,36,4};
HeapSort(num,sizeof(num)/sizeof(int));
for(i=0;i<sizeof(num)/sizeof(int);i++) {
printf("%d\t",num[i]);
}
printf("\n");
}
優點:高效,只需要O(1)的輔助空間。
缺點:不穩定,數據較少時不適合使用。
3.二者複雜度比較