爲什麼要排序
1. 有時應用本身就需要對信息進行排序。例如對財務報表進行排序
2. 很多算法通常把排序作爲關鍵子程序,關鍵技術也體現在排序算法中
算法 | 最壞情況運行時間 | 平均情況/期望運行時間 |
插入排序 | O(n^2) | O(n^2) |
堆排序 | O(n lgn) | -- |
快速排序 | O(n^2) | O(n lgn) |
1. 插入排序
/*插入排序
p[] :待排序數組
len :待排序數組長度
*/
void insertSort(int p[],int len)
{
int i,pos,cur;
for (i = 1; i < len; i++)
{
pos = i -1 ; //有序序列的最後一個元素位置
cur = p[i]; //保存待排序元素的值
while ( pos >= 0 && p[pos] > cur) //如果cur值小於有序數組最後一個元素值,則後移有序
//數組,再檢查前一個有序數組的值,重複以上循環,直到cur不大於有序數組的值
{
p[pos + 1] = p[pos];
pos--;
}
p[pos + 1] = cur; //將待排序元素插入數組中
}
}
2. 堆排序
#define INT_MAX 0x7FFFFFFF
#define INT_MIN (0-INT_MAX)
/*
最大堆排序
a[] :待排序數組
s : 父節點
len : 需要排序的堆長度
*/
void HeapAdjustMax(int a[],int s,int len)//一次篩選的過程
{
int max,tmp;
while(s <= len/2 -1)
{
tmp = (2 * s + 2 >= len) ? INT_MIN : a[2 * s + 2]; // 總數爲偶數,最後一個父節點沒有右孩子
max = (a[2 * s + 1] >= tmp) ? 2 * s + 1 : 2 * s + 2; // max 左右孩子中,最大的孩子值
if(a[max] > a[s]) //大堆小堆比較
{
tmp = a[max];
a[max] = a[s];
a[s] = tmp;
s = max; //交換父節點和子節點的值後,跟蹤到子節點
}
else
break;
}
}
/*最小堆排序*/
void HeapAdjustMin(int a[],int s,int len)//一次篩選的過程
{
int min,tmp;
while(s <= len/2 -1)
{
tmp = (2 * s + 2 >= len) ? INT_MAX : a[2 * s + 2]; // 總數爲偶數,最後一個父節點沒有右孩子
min = (a[2 * s + 1] < tmp) ? 2 * s + 1 : 2 * s + 2; //// min 左右孩子中,最小的孩子值
if(a[min] < a[s]) //大堆小堆比較
{
tmp = a[min];
a[min] = a[s];
a[s] = tmp;
s = min; //交換父節點和子節點的值後,跟蹤到子節點
}
else
break;
}
}
/*
a[] : 待排序數組
n : 數組長度
*/
void HeapSort(int a[],int n)
{
int temp,i;
/*n/2-1 爲倒數第一個非葉子節點*/
for(i = n/2 - 1; i > 0;i--)//通過循環初始化頂堆,最後一個非葉子節點向前找
{
HeapAdjustMin(a,i,n); //HeapAdjustMax(a,i,n);
}
for(i = n;i > 1;i--) //末尾向前移動
{
HeapAdjustMin(a,0,i); //HeapAdjustMax(a,i,n);
temp=a[0];
a[0]=a[i-1];
a[i-1]=temp;//交換
}
}
3. 快速排序
/**************************快速排序法***********************************/
/*
a[] :待排序數組
left:左邊界
right:右邊界
*/
void quickSort(int a[],int left,int right)
{
int i = left;
int j = right;
int temp = a[left]; //此爲基準數
if(left >= right)
return;
while(i != j)
{
while(i < j && a[j] >= temp) //從右向左,找到第一個大於基準數的值,標記
j--;
if(j > i)
a[i] = a[j]; //a[i]已經賦值給temp,所以直接將a[j]賦值給a[i],賦值完之後a[j],有空位
while(i<j && a[i]<=temp) //從左向右,找到一個小於基準的數,標記
i++;
if(i < j)
a[j] = a[i]; //交換,將待排序列以基準數分爲左右兩半,分治思想
}
a[i]=temp; //把基準插入,此時i與j已經相等R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
quickSort(a,left,i-1); /*遞歸左邊*/
quickSort(a,i+1,right); /*遞歸右邊*/
}
測試程序
int main()
{
/* 插入排序*/
int num[] = {13, 7, 1, 8, 5, 12, 9,6};
int i;
int length = sizeof(num)/sizeof(num[0]);
// insertSort(num,length); //插入排序
// HeapSort(num,length); //堆排序
quickSort(num,0,length-1);
for(i=0;i < length;i++)
printf("%d\t",num[i]);
return 0;
}
本文只是算法的實現,具體參考《算法導論》