合并两个有序的数组
已有两个有序的数组,设分别为A和B。要得到合并后的有序数组C。
假设这两个数组长度分别为m和n,则合并后的数组长度为m+n图中A和B数组长度分别为5和4(即m=5,n=4),C数组的长度为9。
算法思路:
初始化(Step1)
-
先创建一个缓冲数组C(C的长度为m+n)
-
设置三个游标,i 和 j 分别指向A和B数组的第一个元素;k 指向C数组的第一个元素
比较并填充(Step2)
-
比较数值:比较 i 游标和 j 游标所指的元素值大小,将较小者填入C数组中。
即比较A[i]和B[j]的大小,并将较小者赋值给C[k]
-
移动游标:将A和B中填入C的那个游标右移(图中是i),将C的游标右移动。
将A or B 还未遍历的元素直接拼接到C(Step3)
因为Step2中,A和B数组的长度不一定相同,并且遍历有先后顺序。因此一定存在A or B中还有未遍历完的元素的情形。
上图描述了两种未遍历完的情形:Case1中A先遍历完,B还未遍历完;Case2中B先遍历完,A还未遍历完。
-
可以根据A和B游标的值和各自的数组长度做比较,从而判断是哪种情形
比如Case1中:A的数组长度是5,游标值也为5(数组下标从0开始)。则可以说明是A数组先遍历完。
-
根据对应的情形,将未遍历完的数组元素直接拼接到C后。
比如Case1中,需要将B中剩余的元素11和12直接拼接到C数组中。
合并算法的小变形
为了便于后续封装利用,做了小小的改动:
两个有序的数组 ( A[p]~A[q]及A[q+1]~A[r]已按递增顺序排序 )
即A和B数组用一个数组A来表示,参数p,q,r代表这个两个子数组的范围。
可以理解为:A[p]~A[q]代表A数组,A[q+1]~A[r]代表B数组
1 /* 2 合并两个有序的子数组 ( A[p]~A[q]及A[q+l]~A[r]已按递增顺序排序 ) 3 输入:整数数组A[p]~A[r],元素个数n 4 下标p , q , r 5 输出:按递增顺序排序的子数组A[p]~A[r] 6 */ 7 void merge(int A[], int p, int q, int r, int n) { 8 int *B = new int[n]; // 建立缓冲区 9 int k = 0; // 指向B的游标,主要用于插入数据进B中 10 int i = p, j = q + 1; 11 while (i <= q && j <= r) { // while循环的跳出条件是:i和j只要有一个超过各种数组的界限 12 if (A[i] >= A[j]) { 13 B[k++] = A[j++]; 14 } else { 15 B[k++] = A[i++]; 16 } 17 } 18 if (i == q+1) { // 说明是前半段先遍历完,把后半段的拼到数组后面 19 while (j <= r) { 20 B[k++] = A[j++]; 21 } 22 } else { 23 while (i <= q) { 24 B[k++] = A[i++]; 25 } 26 } 27 // 将选定的部分替换为B的数组 28 k = 0; 29 for (i = p; i <= r; i++) { 30 A[i] = B[k++]; 31 } 32 delete[] B; 33 }
蹭热打铁(刷Leetcode)
88:合并两个有序数组
https://leetcode-cn.com/problems/merge-sorted-array/
88:merge sorted array
https://leetcode.com/problems/merge-sorted-array/