高级排序
之前我们学习过基础排序,包括冒泡排序,选择排序还有插入排序,并且对他们在最坏情况下的时间复杂度做了分析,发现都是(N^2),而平方阶通过我们之前学习算法分析我们知道,随着输入规模的增大,时间成本将急剧上升,所以这些基本排序方法不能处理更大规模的问题,接下来我们学习一些高级的排序算法,争取降低算法的时间复杂度最高阶次幂。
希尔排序
希尔排序是插入排序的一种,又称 "缩小增量排序”,是插入排序算法的一种更高效的改进版本。
需求:
排序前: {9,1,2,5,7,4,8,6,3,5}
排序后∶{1,2,3,4,5,5,6,7,8,9}
排序原理:
- 选定一个增长量h,按照增长量h作为数据分组的依据,对数据进行分组;
- 对分好组的每一组数据完成插入排序;
- 减小增长量,最小减为1,重复第二步操作。
增长量 h 的确定: 增长量h的值每一固定的规则,我们这里采用以下规则:
int h=1;
while(h<5){
h= 2h+1;
}
/*
* 循环结束后我们就可以确定h的最大值;
* h的减小规则为∶ h=h/2
*/
shellSort.c
static void Swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
static int Compare(int x, int y)
{
return ((x) < (y)) ? (1) : (0);
}
static void shellSort(int *arr, int len)
{
//1.根据数组a的长度﹐确定增长量h的初始值
int h = 1;
while(h < len/2){
h = 2*h+1;
}
//2.希尔排序
while(h >= 1){
//排序
//2.1 找到待插入的元素
for (int i = h; i < len; i++){
//2.2 把待插入的元素插入到有序数列中
for (int j = i; j >= h; j-=h){
//待插入元素是arr[j],比较arr[j], arr[j-h]
if(Compare(arr[j], arr[j-h])){
//交换元素
Swap(&arr[j], &arr[j-h]);
}else{
//否则待插入元素位置合适,结束循环;
break;
}
}
}
//减小h的值
h = h/2;
}
}
run:
递归
定义函数时,在函数内部调用函数本身,称之为递归。
作用:
它通常把一个大型复杂的问题,层层转换为一个与原问题相似的,规模较小的问题来求解。递归策略只需要少量的程序就可以描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
注意事项∶
在递归中,不能无限制的调用自己,必须要有边界条件,能够让递归结束,因为每一次递归调用都会在栈内存开辟新的空间,重新执行函数,如果递归的层级太深,很容易造成栈内存溢出。
归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;
即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
需求:
排序前:{8,4,5,7,1,3,6,2}
排序后:{1,2,3,4,5,6,7,8}
排序原理:
- 尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止。
- 将相邻的两个子组进行合并成一个有序的大组;
- 不断的重复步骤2,直到最终只有一个组为止。
#### mergeSort.c
。。。。