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;
}