一:主要思想
将若干个有序序列逐步归并,最终合成一个有序队列
二:问题
1:怎样构造初始有序队列
2:两个相邻的队列如何合成一个有序队列
3:怎样完成一趟和合并(二种我们只完成了前面相邻的)
4:完成归并结束的标志是什么
三:问题的解决
1:初始长度为1的有序序列
2:相邻数组中按照大小依次放到暂存数组
/** * 1:我们将代排序列看成长度为1的n个有序序列 2:两个相邻的如何合并成一个有序序列 s:第一个数列第一个位置 m:第一个数列最后一个位置 * t:第二个数列某位置 k:合并之后队列的首位置 * * 我们传的是原数组,暂存数组,有序队列第一位置,最后一个位置,有序队列第二个末位置 */ public void merge(int r[], int r1[], int s, int m, int t) { int i, j, k; i = s; j = m + 1; k = s; while (i < m && j < t) { if (r[i] < r[j]) r1[k++] = r[k++]; else r1[k++] = r[j++]; } // 第一个没处理完或者第二个,没处理完 if (i < m) { while (i < m) r1[k++] = r[i]; } else { // 第二个数组,没处理完 while (j < t) r1[k++] = r[j++]; } }
三:怎么样把剩下的一趟合并
3.1:我们分三种情况
1:合并的全是前面的
2:合并到末尾
2.1:剩一个长度小于h的和长度为h的
2.2:只剩下一个长度为h的
public void MergePass(int r[], int r1[], int n, int h) { int i = 1; /** * 1:合并两个长度都为h; 2:合并一个H,另一个小于h(末尾情况) 3:合并自剩下一个h,我们把它挂在合并之后的数组中 */ // 1:合并长度都为h的有序序列 while (i < n - 2 * h + 1) { // 看1是否减掉,我们看i是否包含里面 merge(r, r1, i, i + h - 1, i + 2 * h - 1); // i的值后移2h未 i += 2 * h; } // 2:合并到最后后剩一个长度小于h,和一个长度为h的数组 if (i < n - h + 1) { merge(r, r1, i, i + h - 1, n); } else { for (int k = i; k < n; k++) { r1[k] = r[k]; } } }
四: 结束标志
初始长度为1,我们判断最后队列长度是否为n,作为结束标志
/** *判断结束 */ public void MergeSort(int r[],int r1[],int n) { int h=1; while(h<n) { MergePass(r, r1, n, h);//排序好的数组我们放到暂存数组中了 h=2*h; MergePass(r1,r ,n, h);//我们把暂存数组中的倒到我们原数组中和 h=2*h; } }