目录
一. 归并排序
1.1 归并排序的数据算法数排实现思想
1.2 归并排序的递归实现
1.2.1 归并排序递归实现的思想
1.2.2 归并排序递归实现的代码
1.3 归并排序的非递归实现
1.3.1 归并排序非递归实现的思想
1.3.2 归并排序非递归实现的代码
1.4 归并排序的时间复杂度分析
二. 计数排序
2.1 计数排序的思想
2.2 计数排序函数代码
2.3 计数排序的时间复杂度、空间复杂度及适用情况分析
归并排序采用分治的思想实现,对于具有n个数据的待排序数组,先将其前半部分和后半部分都排列为有序,然后将前半部分和后半部分视为不同的两个有序序列,将这两个有序序列合并,得到的新的有序序列就是原序列排序后的结果 。图1.1展示了归并排序的排序排序实现过程 。
由图1.1,为了保证前半部分和后半部分有序,在将数组拆分为两部分后继续拆分,直到每组数据中仅有一个数据,单个数据可视为有序序列。完成整体拆分后,即拆到每组只有一个数据,将数据合并为每组两个数据,每组的归并两个数据有序,之后继续执行合并操作,直到数组中所有数据有序。
void _MergeSort(int* a, int* tmp, int left, int right){//如果区间左值大于等于区间右值,停止拆分if (left >= right){return;}int mid = (left + right) / 2;_MergeSort(a, tmp, left, mid); //左区间归并排序_MergeSort(a, tmp, mid + 1, right); //右区间归并排序//区间[left,mid] [mid+1,right]中的数据均有序//合并两组数据成新的有序序列int begin1 = left, end1 = mid; //左区间的起始下标和结束下标int begin2 = mid + 1, end2 = right; //右区间的起始下标和结束下标//排升序int index = begin1; //控制tmp的下标//先将[left,right]区间的数据按顺序排序存入tmp的[left,right],然后拷贝会原数组awhile (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}//将tmp中的数据拷贝回afor (int i = left; i <= right; ++i){a[i] = tmp[i];}}void MergeSort(int* a, int n) //递归实现归并排序函数{assert(a);//开辟临时空间存储用于临时存储部分排序后的数据int* tmp = (int*)malloc(n * sizeof(int)); if (NULL == tmp){printf("malloc failn");exit(-1);}_MergeSort(a, tmp, 0, n - 1);free(tmp);tmp = NULL;}
归并排序的非递归实现思想与递归类似,都是先将待排序数组中的有数据分组,先将数组中的每个数据单独视为一组,从左侧第一组数据开始,将每两个数据合并为新的组,然后继续按组合并数据,直到完成排序 。
与递归不同的和计是,非递归引入变量gap来控制两组待合并的有序序列首元素的下标之差。如图1.2所示,取begin1和end1分别为左侧有序序列起始下标和结束下标,取begin2和end2位右侧有序序列的数据算法数排起始下标和结束下标,程序中用循环参数i来控制左侧有序序列起始下标,因此:左侧有序序列下标范围[i, i+gap-1],即[begin1,end1],右侧有序序列下标范围是[i+gap,i+2*gap-1],即[begin2,end2] 。将左右两边的结构基础有序序列合并,使区间[begin1,end2]之间的数据有序。
更新gap的排序排序值依次为2、4、8、....,重复执行上段叙述的操作,直到gap 图1.2展示的数组有n=8个数据,满足,因此,begin1、end1、begin2、end2全部没有发生越界,但是,如果待排序数据个数不满足
,那么end1、begin2 、end2则有可能发生越界,begin1一定不会发生越界
。越界可分三种情况进行讨论: