以下原理及实现均为个人理解,如有错误或更优解,欢迎留言指正!
排序算法概述
盗个图
转自:https://www.cnblogs.com/onepixel/articles/7674659.html
排序算法复杂度
备注:以下排序算法默认由小到大排序
- 交换排序
- 冒泡排序
算法简介
- 从右向左依次对比相邻元素,将较小值交换到左边;
- 每一轮循环可将最小值交换到最左边;
- 下一轮从之后的位置开始重复1,2 过程,直至完成整个数组。
算法实现
int bubble_sort(int array[], int len)
{
if(NULL == array || len < 1)
{
return -1;
}
int tmp = 0;
int i = 0, j = 0;
for(i=0; i<len; i++)
{
for(j=len-1; j>i; j--)
{
if(array[j-1] > array[j])
{
tmp = array[j-1];
array[j-1] = array[j];
array[j] = tmp;
}
}
}
return 0;
}
- 快速排序
算法简介
- 选择一个元素赋值给哨兵sentinel,默认选择左边第一个元素,这样第一个元素的位置就空出来了;
- 先从最右边元素开始依次跟哨兵比较大小,大于等于哨兵的元素原地不动,遇到小于哨兵的元素则终止循环,把该元素赋值到左侧空出来的位置,同时左侧索引值自增,这时该元素原来的位置就空出;
- 然后从左侧元素开始依次跟哨兵比较大小,小于等于哨兵的元素原地不动,遇到大于哨兵的元素则终止循环,把该元素赋值到右侧空出来的位置,同时右侧索引值自减;
- 依次循环2,3 步,直至左侧索引等于右侧索引,则完成一轮循环,把哨兵赋值到该索引位置。
- 再分别递归地对哨兵左侧和右侧的子数组进行1,2,3,4 步,直至递归子数组只有一个元素,则排序
算法实现
int quick_sort_core(int array[], int left, int right)
{
if(NULL == array || left < 0 || right < left)
{
printf("params error!\n");
return -1;
}
int l = left, r = right;
int sentinel = array[l];
while(l < r)
{
while((l < r) && array[r] > sentinel)
{
r--;
}
if(l < r)
{
array[l++] = array[r];
}
while((l < r) && array[l] < sentinel)
{
l++;
}
if(l < r)
{
array[r--] = array[l];
}
}
array[l] = sentinel;
if(l > left)
{
quick_sort_core(array, left, l-1);
}
if(r < right)
{
quick_sort_core(array, r+1, right);
}
return 0;
}
int quick_sort(int array[], int len)
{
if(NULL == array || len < 1)
{
printf("params error!\n");
return -1;
}
int i = 0;
int left = 0, right = len - 1;
int result = quick_sort_core(array, left, right);
if(result != 0)
{
return -1;
}
return 0;
}
- 插入排序
- 直接插入排序
算法简介
- 左边第一个元素可作为有序子数组;
- 从第二个元素开始,依次向前比较,大于该元素的则向右移一位,直到比该元素小的元素,插入其后;
- 依次向后推进,直至整个数组成为有序数组
算法实现
int insert_sort(int array[], int len)
{
if(NULL == array || len < 1)
{
return -1;
}
int tmp = 0;
int i = 0, j = 0;
for(i = 1; i < len; i++)
{
tmp = array[i];
for(j = i-1; j >= 0 && tmp < array[j]; j--)
{
array[j+1] = array[j];
}
array[j+1] = tmp;
}
return 0;
}
- 希尔排序
算法简介
- 首先选择一个步长值gap,以步长值为间隔把数组分为gap个子数组 i + n*gap,i < gap;
- 对每个子数组进行插入排序;
- 逐步减小步长 gap = gap/3 + 1,重复对数组进行1,2 步骤;
- 当步长值减为1时,相当于对数组进行一次直接插入排序。
算法优点
相对于直接插入排序,希尔排序要高效很多,因为当gap 值较大时,对子数组进行插入排序时要移动的元素很少,元素移动的距离很大,这样效率很高;在gap逐渐减小过程中,数组中元素已逐渐接近排序的状态,所以需要移动的元素逐渐减少;当gap为1时,相当于进行一次直接插入排序,但是各元素已接近排序状态,需要移动的元素很少且移动的距离都很小。
算法实现
int shell_sort(int array[], int len)
{
if(NULL == array || len < 1)
{
return -1;
}
int tmp = 0;
int i = 0, j = 0, k = 0, gap = len;
do
{
gap = gap/3 + 1;
for(i = 0; i < gap; i++)
{
for(j = i+gap; j < len; j = j+gap)
{
tmp = array[j];
for(k = j-gap; k >= i && tmp < array[k]; k = k-gap)
{
array[k+gap] = array[k];
}
array[k+gap] = tmp;
}
}
} while(gap > 1);
return 0;
}
- 选择排序
- 简单选择排序
算法简介
- 从右向左依次对比相邻元素,将较小值交换到左边;
- 每一轮循环可将最小值交换到最左边;
- 下一轮从之后的位置开始重复1,2 过程,直至完成整个数组。
算法实现