1.归并排序:是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
例:设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11;
逆序数为14;
2.基数排序:属于“分配式排序”又称“桶子法或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
附:各种排序时空复杂度对比
归并排序实现:
#include<stdio.h>
#include<stdlib.h>
void Merge(int arr[], int tmp[], int startindex,
int mid, int endindex)
{
int i = startindex;
int j = mid + 1;
int k = startindex;
while (i < mid + 1 && j < endindex + 1)
{
if (arr[i] <= arr[j])
{
tmp[k++] = arr[i++];
}
if (arr[i] > arr[j])
{
tmp[k++] = arr[j++];
}
}
while (i < mid + 1)
{
tmp[k++] = arr[i++];
}
while (j < endindex + 1)
{
tmp[k++] = arr[j++];
}
for (int i = startindex; i <= endindex; ++i)
{
arr[i] = tmp[i];
}
}
void MergeS(int arr[], int tmp[], int startindex, int endindex)
{
if (startindex < endindex)
{
int mid = (startindex + endindex) / 2;
MergeS(arr, tmp, startindex, mid);
MergeS(arr, tmp, mid + 1, endindex);
Merge(arr, tmp, startindex, mid, endindex);
}
}
void MergeSort(int arr[], int len)
{
int *tmp = (int*)malloc(sizeof(arr[0])*len);
MergeS(arr, tmp, 0, len - 1);
free(tmp);
}
基数排序实现:
include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define MAXSIZE 10
void Show(int arr[], int len)
{
for (int i = 0; i < len; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//9031 ==> 4
int FindMaxFinger(int arr[], int len)
{
int maxnum = arr[0];
for (int i = 1; i < len; ++i)
{
if (arr[i]>maxnum)
{
maxnum = arr[i];
}
}
int count = 0;
while (maxnum != 0)
{
maxnum /= 10;
count++;
}
return count;
}
//893 1 ==> 9
int FindFinNumber(int num, int fin)
{
return num / (int)pow(10.0, fin) % 10;
}
void Radix(int arr[], int len, int fin)
{
int backet[10][MAXSIZE] = {};
int finnum = 0;
int num[10] = {};
for (int i = 0; i < len; ++i)
{
finnum = FindFinNumber(arr[i], fin);
backet[finnum][num[finnum]] = arr[i];
num[finnum]++;
}
int aindex = 0;
int bindex = 0;
for (int i = 0; i < 10; ++i)
{
bindex = 0;
while (bindex != num[i])
{
arr[aindex++] = backet[i][bindex++];
}
}
}
void RadixSort(int arr[], int len)
{
int max = FindMaxFinger(arr, len);
for (int i = 0; i < max; ++i)
{
Radix(arr, len, i);
}
}