1.歸併排序
分析:
歸併排序使用分治思想,原理是
①將一個無序數列分成兩個序列後,對序列進行排序後,再將兩個有序序列合併成一個有序序列;
②分開的兩個序列又可以進行再分排序然後合併從而形成問題的子問題。
#include <stdio.h>
#include <stdlib.h>
void merge(int *a, int *ans, int s, int m, int t){
int ak, bk, ansk;
ak = s, bk = m+1, ansk = s;
while(ak<=m&&bk<=t){
*(ans+ansk++) = (*(a+ak)<*(a+bk))?*(a+ak++):*(a+bk++);
}
for(; ak<=m; ak++){
*(ans+ansk++) = *(a+ak);
}
for(; bk<=t; bk++){
*(ans+ansk++) = *(a+bk);
}
}
void mergesort(int *a, int n, int low, int high, int *ans){
int mid;
int *temp;
temp = (int*)malloc(sizeof(int)*n); //save the result of sort
if(low==high){
*(ans+low) = *(a+low);
return;
}
mid = (low+high)/2;
//sort a[low...mid]
mergesort(a, n, low, mid, temp);
//sort a[mid+1, high]
mergesort(a, n, mid+1, high, temp);
//merge temp[low...mid] temp[mid+1, high] into ans[low...high]
merge(temp, ans, low, mid, high);
free(temp);
}
int main(void){
int data[] = {2,4,8,5,1,6,3,10,9};
int n = sizeof(data)/sizeof(int);
int ansk;
int *ans = (int*)malloc(sizeof(int)*n);
int *temp = (int*)malloc(sizeof(int)*n);
mergesort(data, n, 0, n-1, ans);
for(ansk=0; ansk<n; ansk++){
printf("%d ", *(ans+ansk));
}
printf("\n");
return 0;
}
2.堆排序
分析:
①將無序數列視爲一棵完全二叉樹的節點,並以層逐個加入樹中,樹的節點數/2的節點必有孩子;
②堆排序(結果需要從小到大排序)旨在將最大值元素移至樹根處,並將其與樹最後節點交換即可;
③對於一個結點,需要滿足一個條件a[i]>a[2*i]和a[i]>a[2*i+1];
④當一個結點與其孩子交換後,需要對交換的孩子向下調整,保證滿足條件③;
所以堆排序的步驟則爲:
1)由無序數組視爲一棵無安全二叉樹的節點,從擁有孩子的節點開始,先對該樹進行調整,使其滿足條件③,此時形成大頂堆;
2)樹根結點與樹最後節點交換後,由於已經形成大頂堆,所以第二大的元素必爲根結點的孩子,所以只需要進行向下調整即可將最大元素置於根結點位置;假設第二大元素不爲根結點孩子,那麼必然位於根結點孩子的左或右子樹,而由於第三個條件,子樹的根結點必爲最大,所以必定不滿足條件③。
#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void heapadjust(int *data, int n, int i){
//downward adjustment
int k;
int max;
for(k=i+1; k<=n/2; k++){
//compare root,lchild,rchild
max = (*(data+k-1)>*(data+2*k-1))?k-1:2*k-1;
if(2*k<n)
max = (*(data+max)>*(data+2*k))?max:2*k;
if(max==k-1)
continue;
else{
swap(data+k-1, data+max);
heapadjust(data, n, max);
}
}
}
void heapsort(int n, int *data){
int k;
for(k=0; k<n; k++){
swap(data, data+n-k-1);
heapadjust(data, n-k-1, 0);
}
}
int main(void){
int data[]={5,4,3,2,1};
int k;
int n=sizeof(data)/sizeof(int);
for(k=n/2; k>=0; k--)
heapadjust(data, n, 0); //initialize heap
heapsort(n, data);
for(k=0; k<n; k++){
printf("%d ", *(data+k));
}
printf("\n");
return 0;
}
3.快速排序
分析:
①尋找位置s,將無序數列第一個元素放置於as,使得as>aj (t<j<s),as<ai (n>i>s);
②對無序數列at,...,as-1和as+1,...,an重複步驟①即可,知道t=s-1或s+1=n位置。
#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int find_mid(int *d, int low, int high){
int k;
while(low<high){
while(*(d+low)<*(d+high)&&low<high)
high--;
swap(d+low, d+high);
while(*(d+low)<*(d+high)&&low<high)
low++;
swap(d+low, d+high);
}
return low;
}
void quicksort(int *d, int low, int high){
int mid;
if(low<high){
mid = find_mid(d, low, high);
quicksort(d, low, mid-1);
quicksort(d, mid+1, high);
}
}
int main(void){
int data[] = {5,9,7,8,2,4,6,3,1};
int n = sizeof(data)/sizeof(int);
int k;
quicksort(data, 0, n-1);
for(k=0; k<n; k++)
printf("%d ", *(data+k));
printf("\n");
return 0;
}