阿里巴巴做国际网站要多少钱,北京网页制作案例,专门做衣服的网站有哪些,2017网站制作报价单目录
归并排序的递归实现
代码实现
归并排序的非递归实现
代码实现 归并排序的思想很简单——分治法。简单地说#xff0c;归并排序的是将序列拆分成几段子序列#xff0c;将每一段子序列分别进行排序#xff0c;排好之后再将有序的子序列归并#xff08;有点像合并两…
目录
归并排序的递归实现
代码实现
归并排序的非递归实现
代码实现 归并排序的思想很简单——分治法。简单地说归并排序的是将序列拆分成几段子序列将每一段子序列分别进行排序排好之后再将有序的子序列归并有点像合并两个有序数组成为一个有序的序列。
例如要排序数列10、6、7、1、3、9、4、2 将序列拆分为 2 个子序列 继续拆分 继续拆分 至此每个子序列的长度都为 1 因为只有一个数所以可认为是有序序列
现将子序列两两归并即合并两个有序序列 继续归并
继续归并
以上就是归并排序的整个过程很显然归并排序的实现应该离不开递归的思想。 归并排序的递归实现
归并排序的递归实现较为简单需要注意的有两点
1. 归并的过程并非在原数组上直接改动而是开辟一个临时数组在临时数组上进行排序排好之后将临时数组的内容全部拷贝到原数组
2. 代码中使用的是二路归并如上图所示每次将序列拆分为两个子序列。
代码实现
void _MergeSort(int* a, int begin, int end, int* tmp)
{//递归的结束条件//当序列只有一个元素时或序列不存在时if (begin end)return;//将序列进行拆分 //[begin,mid] [mid1,end]int mid (begin end) / 2;//拆分的过程_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid1, end, tmp);//以下为归并的过程int begin1 begin, end1 mid;int begin2 mid1, end2 end;int i begin;//归并合并两个有序序列while (begin1 end1 begin2 end2){if (a[begin1] a[begin2]){tmp[i] a[begin1];}else{tmp[i] a[begin2];}}//如果第二段序列先结束while (begin1 end1){tmp[i] a[begin1];}//如果第一段序列先结束while (begin2 end2){tmp[i] a[begin2];}//将临时数组的数据拷贝回原数组memcpy(a begin, tmp begin, sizeof(int) * (end - begin 1));
}void MergeSort(int* a,int n)
{//开辟一个临时数组int* tmp (int*)malloc(sizeof(int) * n);if (tmp NULL){perror(malloc fail);exit(-1);}_MergeSort(a, 0, n - 1, tmp);//释放与置空free(tmp);tmp NULL;
}
归并排序的非递归实现
非递归与递归作用思想基本相同。递归实现时因为拆分序列时采用的是递归的方式所以通过传递参数就可以控制子序列的长度。但是非递归不行非递归通过变量 rangeN 来控制序列的长度或间隔每次让 rangeN * 2 例如 但是由于 rangeN 每次都 *2 而我们排序的序列长度不可能总是 2 的倍数所以 可能会有数组越界访问的风险。例如 现将两个子序列归并并将数据拷贝回原数组时就会发生越界
当然这只是其中一种越界的可能情况——第二段序列发生越界原因是右边界 end2 大于 n
实际操作中一共会有三种情况导致越界
两段序列的区间分别为 [begin1,end1] [begin2,end2]
1. end1 n
2. begin n
3.end2 n;
所以当这三种情况发生时需要修正区间以上述用例为例 end2 大于 n 时令 end2 n-1即可
代码实现
void MergeSortNonR(int* a, int n)
{//开辟一个临时数组int* tmp (int*)malloc(sizeof(int) * n);if (tmp NULL){perror(malloc fail);exit(-1);}int rangeN 1;while (rangeN n){// i 控制访问子序列的位置for (int i 0; i n; i 2 * rangeN){//拆分为两段子序列//[begin1,end1] [begin2,end2]int begin1 i, end1 i rangeN - 1;int begin2 i rangeN, end2 i 2 * rangeN - 1;int j i;//判断是否发生越界的三种情况如果有就修正区间if (end1 n){end1 n - 1;//将第二段序列改为不存在的序列即可begin2 n;end2 n - 1;}else if (begin2 n){//将第二段序列改为不存在的序列即可begin2 n;end2 n - 1;}else if (end2 n){//修正区间end2 n-1;}while (begin1 end1 begin2 end2){if (a[begin1] a[begin2]){tmp[j] a[begin1];}else{tmp[j] a[begin2];}}//如果第二段序列先结束while (begin1 end1){tmp[j] a[begin1];}//如果第一段序列先结束while (begin2 end2){tmp[j] a[begin2];}}//将临时数组的内容拷贝回原数组memcpy(a, tmp, sizeof(int) * n);//控制间隔rangeN * 2;}//释放与置空free(tmp);tmp NULL;
}