整理归并排序
二路归并
将两个有序表合并成一个有序表,称为二路归并。
合并两个有序序列
现在有两个单调上升序列,请将这两个序列合并为一个单调上升序列。
例如 a[7]={3,7,10,11,13,14,15} b[6]={2,4,8,9,10,12};
合并为c[13]={2,3,4,7,8,9,10,10,11,12,13}
步骤: 1. 设置两个变量,分别表示序列 a和序列b的下标 ,i表示序列a的下标,j表示序列b的下标,那么在取数时就可以是a[i]和b[j],把这两个元素进行比较,如果a[i]更小,那么将a[i]存入到c数组中,使用k表示存储的个数 k++,c[k]=a[i]; 否则,将b[j]存储到c数组中,k++,c[k]=b[j];直到a数组或者b数组存完为止。
2.此时会存在a数组或者b数组没有存完的情况,那么只需要将剩余的数据依次存入到c中即可。
第一次 i=0 j=0 a[0]为3 b[0]为2 a[i]>b[j] 将b[j]存入到c[k]中 那么序列 c[13]={2}; j向后变化一次 j++.
第二次 i=0 j=1 a[0]为3 b[1]为4 a[i]<b[j] 将a[i]存入到c[k]中 那么 序列 c[13]={2,3}; i向后变化一次 i++.
第三次 i=1 j=1 a[1]为7 b[1]为4 a[i]>b[j] 将b[j]存入到c[k]中 那么序列 c[13]={2,3,4}; j向后变化一次 j++.
第四次 i=1 j=2 a[1]为7 b[2]为8 a[i]<b[j] 将a[i]存入到c[k]中 那么 序列 c[13]={2,3,4,7}; i向后变化一次 i++.
第五次 i=2 j=2 a[2]为10 b[2]为8 a[i]>b[j] 将b[j]存入到c[k]中 那么序列 c[13]={2,3,4,7,8}; j向后变化一次 j++.
第六次 i=2 j=3 a[2]为10 b[3]为9 a[i]>b[j] 将b[j]存入到c[k]中 那么序列 c[13]={2,3,4,7,8,9}; j向后变化一次 j++.
第七次 i=2 j=4 a[2]为10 b[4]为10 a[i]==b[j] 两数相等,优先存前面序列中的数据, 将a[i]存入到c[k]中 那么序列 c[13]={2,3,4,7,8,9,10}; i向后变化一次 i++.
第八次 i=3 j=4 a[3]为11 b[4]为10 a[i]>b[j] 将b[j]存入到c[k]中 那么序列 c[13]={2,3,4,7,8,9,10,10}; j向后变化一次 j++.
第九次 i=3 j=5 a[3]为11 b[5]为12 a[i]<b[j] 将a[i]存入到c[k]中 那么序列 c[13]={2,3,4,7,8,9,10,10,11}; i向后变化一次 i++.
第十次 i=4 j=5 a[3]为13 b[5]为12 a[i]>b[j] 将b[j]存入到c[k]中 那么序列 c[13]={2,3,4,7,8,9,10,10,11,12}; j向后变化一次 j++.
此时b数组已经存储完毕,a数组还剩一个数据没有存储
那么把a数组中剩余的数据全部存储到c数组中,那么c[13]={2,3,4,7,8,9,10,10,11,12,13,14,15};
代码如下:
C++
//假设a序列有n个数,b序列有m个数
//本段代码以下标0开始
i=0;j=0;
while(i<n&& j<m){
if(a[i]<b[j]){
c[k]=a[i];
k++;
i++;
}else{
c[k]=b[j];
k++;
j++;
}
}
//如果a数组中还有数
while(i<n)
{
c[k]=a[i];
k++;
i++;
}
//如果b数组中还有数
while(j<m)
{
c[k]=b[j];
k++;
j++;
}
//最终存储了k个数在数组c中,可以从0到k-1遍历数组c
归并排序
归并排序就是在二路归并的基础进行的。原理是将原来的无须序列一步一步拆分成一个个的元素。可以把这一个个元素看成一个单独的有序序列,之后再将每两个序列进行二路归并,逐步合成为一个序列的过程。
例如:无序序列 a[7]={3,1,4,7,2,5,6};
第一次可以分解为 {3,1,4,7} {2,5,6}
第二次可以分解为 {3,1} {4,7} {2,5} {6}
第三次可以分解为 {3} {1} {4} {7} {2} {5} {6}
然后两两进行归并
第一次归并:分别将1和2 3和4 5和6 进行二路归并
结果为 {1,3} {4,7} {2,5} {6}
第二次归并分别将1和2 3和4进行二路归并
结果为{1,3,4,7} {2,5,6}
第三次将1和2进行二路归并
结果为{1,2,3,4,5,6,7}
代码如下:
C++
//本段代码以下标1开始
void merge(int l,int r) {
if(l>=r) return;
int mid=(l+r)/2;
merge(l,mid);
merge(mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid && j<=r) { //以两段有序序列的大小依次存放到b数组(从小到大)
if(a[i]>a[j]) {
b[++k]=a[j++];//更小的数放在前面
} else {
b[++k]=a[i++];
}
}
while(i<=mid) { //如果第一段序列没有排序完毕,继续存到 b
b[++k]=a[i++];
}
while(j<=r) {//如果第二段序列没有排序完毕,继续存到b
b[++k]=a[j++];
}
for(int i=l; i<=r; i++) {//更新a数组
a[i]=b[i-l+1];
}
}
如果习惯于从下标1开始,请私信博主,会对部分内容进行更改哦!