归并排序
来源:互联网 发布:php管理上传文件 编辑:程序博客网 时间:2024/06/04 17:59
归并排序算法链接
排序思想
① 初始时,将每个记录看成一个单独的有序序列,则n个待排序记录就是n个长度为1的有序子序列;
② 对所有有序子序列进行两两归并,得到┏n/2┓个长度为2或1的有序子序列——一趟归并;
③ 重复② ,直到得到长度为n的有序序列为止。
上述排序过程中,子序列总是两两归并,称为2-路归并排序。其核心是如何将相邻的两个子序列归并成一个子序列。设相邻的两个子序列分别为:
{R[k], R[k+1], …, R[m]}和{R[m+1], R[m+2],…, R[h]},将它们归并为一个有序的子序列:
{DR[l], DR[l+1], …, DR[m], DR[m+1], …, DR[h] }
排序示例
设有9个待排序的记录,关键字分别为23, 38, 22, 45, 23, 67, 31, 15, 41,归并排序的过程如图1所示。
算法实现
1. 非递归方式
/* 二路归并算法 *//* 将有序的R[low..mid]和X[mid+1..high]归并为有序的DR[low..high] */void Merge(int R[], int DR[], int low, int mid, int high){ int i, j, k; i = k = low; j = mid+1; while(i<=mid && j<=high) { if(R[i] <= R[j]) /* 比较两个子序列 */ DR[k++] = R[i++]; else DR[k++] = R[j++]; } while(i<=mid) /* 将R中剩余元素R[i...mid]复制到DR */ DR[k++] = R[i++]; while(j<=high) /* 将R中剩余元素R[j...high]复制到DR */ DR[k++] = R[j++];}/* 一趟归并排序 *//* 一趟归并排序都是从前到后,依次将相邻的两个有序子序列归并为一个,
/* 且除最后一个子序列外,其余每个子序列的长度都相同。 */
/* 设这些子序列的长度为d,则一趟归并排序的过程是: *//* 从j=0开始,依次将相邻的两个有序子序列R[j…j+d-1]和R[j+d…j+2d-1]进行归并;
/* 每次归并两个子序列后,j后移动2d个位置,即j=j+2d; */
/* 若剩下的元素不足两个子序列时,分以下两种情况处理: *//* ① 剩下的元素个数>d:再调用一次上述过程,将一个长度为d的子序列和不足d的子序列进行归并; *//* ② 剩下的元素个数≤d:将剩下的元素依次复制到归并后的序列中。 */
void Merge_pass(int R[], int DR[], int d, int n){ int j=0; while ((j+2*d-1)<n) { Merge(R, DR, j, j+d-1, j+2*d-1); j=j+2*d; } /* 子序列两两归并 */ if(j+d-1<n) /* 剩余元素个数超过一个子序列长度d */ Merge(R, DR, j, j+d-1, n); else Merge(R, DR, j, n, n); /* 剩余子序列复制 */}/* 开始归并时,每个记录是长度为1的有序子序列,对这些有序子序列逐趟归并,每一趟归并后有序子序列的长度均扩大一倍; */
/* 当有序子序列的长度与整个记录序列长度相等时,整个记录序列就成为有序序列。算法是: */
BOOL Merge_sort(int R[], int DR[], int length){ int d=1; while(d<length) { Merge_pass(R, DR, d, length); Merge_pass(DR, R, 2*d, length); d=4*d; } return true;}
2. 递归方式
//将有二个有序数列R[low...mid]和R[mid+1...high]合并。void Merge(int R[], int low, int mid, int high, int temp[]){ int i, j, k; i = k = low; j = mid + 1; while (i <= mid && j <= low) { if (R[i] <= R[j]) temp[k++] = R[i++]; else temp[k++] = R[j++]; } while (i <= mid) temp[k++] = R[i++]; while (j <= high) temp[k++] = R[j++]; for (i = 0; i < k; i++) R[low + i] = temp[i];}void mergeSort(int R[], int low, int high, int temp[]){if (low < high){int mid = (low + high) / 2;mergeSort(a, low, mid, temp); //左边有序mergeSort(a, mid + 1, high, temp); //右边有序Merge(a, low, mid, high, temp); //再将二个有序数列合并}}bool MergeSort(int R[], int n){int DR[n] = {0};mergeSort(R, 0, n - 1, DR);return true;}
算法分析
具有n个待排序记录的归并次数是㏒2n,而一趟归并的时间复杂度为O(n),则整个归并排序的时间复杂度无论是最好还是最坏情况均为O(n㏒2n)。在排序过程中,使用了辅助向量DR,大小与待排序记录空间相同,则空间复杂度为O(n)。归并排序是稳定的。
- 归并排序-归并排序
- 归并和归并排序
- 归并与归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 排序::归并
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- poj 2051 - Argus(堆)
- 动态sql中使用临时表的实例
- notepad++ 设置豆沙绿
- hibernate映射时表名与列名前缀的设置
- JavaScript对象学习经验整理
- 归并排序
- 【VS-C++】WinSocket开发时提示无法解析的外部符号
- 屏幕间的跳转和传值
- Linux内存机制
- 无法找到会话标识符。启用检查 PLUSTRACE 角色
- mysql的基本操作(初学者)
- 设计一个类,该类不能被继承,且只能实例化3次
- Oracle物化视图语法
- readers-writers problems