本文章包括所有基本排序算法(和其中一些算法的改进算法):
直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序、快速排序、归并排序、基数排序。
算法复杂度比较:
算法分类
一、直接插入排序
一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中。
它的算法步骤可以大致归纳如下:
从未排好的序列中拿出首元素,并把它赋值给temp变量;
从排好的序列中,依次与temp进行比较,如果元素比temp大,则将元素后移(实际上放置temp的元素位置已经空出)
直到找到一个元素比temp小, 将temp放入该位置;
因此,从上面的描述中我们可以发现,直接插入排序可以用两个循环完成:
第一层循环:遍历待比较的所有数组元素
第二层循环:将本轮选择的元素(selected)与已经排好序的元素(ordered)相比较。
如果:selected > ordered,那么将二者交换
#include <stdio.h>
void InsertSort(int *a, int len)
{
int i, j, tmp;
for(i=1; i<len; i++){ //i指向无序区第一个元素
tmp = a[i];
j = i - 1; //j指向有序去第一个元素
// j往前遍历,找到比a[i]小的,插入到此处。比a[i]大的后移
while(j>=0 && tmp<a[j]){ //小于号换成大于号则是从大到小排序
a[j+1] = a[j];
j--;
}
a[j+1] = tmp; //插入到空出来的位置
}
return;
}
int main()
{
int a[] = {1,3,63,5,78,9,12,52,8};
int n = sizeof(a)/sizeof(int),i;
InsertionSort(a, n);
for(i=0; i<n; i++)
printf("%d ", a[i]);
return 0;
}
二、折半插入排序
与直接插入算法的区别在于:在有序表中寻找待排序数据的正确位置时,使用了折半查找/二分查找。
减少了比较的次数,但没有减少插入的次数。时间复杂度仍为O(n^2),但比直接插入排序稍微快一点。
void BinaryInsertSort(int *a, int len)
{
int i, j, low, high, tmp;
for(i=1; i<len; i++){
tmp = a[i];
j = i - 1;
low = 0;
high = i - 1;
while(low<=high){
int mid = (low + high) / 2;
if(tmp>a[mid])
low = mid + 1;
else
high = mid - 1 ;
}
while(j>=low && tmp<a[j]){ //小于号换成大于号则是从大到小排序
a[j+1] = a[j];
j--;
}
a[j+1] = tmp;
}
return;
}
三、希尔排序法
希尔排序又叫缩小增量排序
基于直接插入排序,基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
希尔的思想也很简单就是一个h-sort的插入算法——每相邻h个元素进行插入排序
如果h比较大,那么子数组会很小,用插入效率高
如果h很小,这时候数组基本有序,插入效率也很高
void ShellSort(int arr[], int len)
{
int step;
int i, j;
int tmp;
for(step = len/2; step > 0; step = step/2) // 比直接插入排序多了一层循环
{
for(i = step; i < len; i++) // 直接插入排序可以看成step为1的希尔排序。把这里的Step都替换成1,就是直接插入排序
{
j = i - step;
tmp = arr[i];
while(j>=0 && tmp<arr[j])
{
arr[j+step] = arr[j];
j = j - step;
}
arr[j+step] = tmp;
}
}
return;
}
四、简单选择排序
排序思路是:每次从未排序的序列中选出一个最小值,并把它放在已排好序的序列的序尾。这样就形成了一个有序序列(从小到大)。

本文详述了各种经典排序算法,包括直接插入、折半插入、希尔、选择、堆、冒泡、快速、归并和基数排序,并讨论了算法的改进方法,如快速排序的三数取中和归并排序的非递归实现。
最低0.47元/天 解锁文章
1332

被折叠的 条评论
为什么被折叠?



