归并排序算法
public class MergeSort {
static int[] s = {2, 1, 10, 20, 3 ,2, 44, 23, 7, 6, 84, 100};
static int mergeCalledCounter;
private static void merge(int[] a, int p, int q, int r) {
if (p < 0 || r > a.length-1) {
System.out.println("wrong parameters");
return;
}
int n1 = q-p+1;
int n2 = r-q;
int i = 0, j = 0;
int[] left = new int[n1+1];
int[] right = new int[n2+1];
for (; i<n1; i++) {
left[i] = a[p+i];
}
for (; j<n2; j++) {
right[j] = a[q+j+1];
}
// 这里使用了哨兵,可以换另一种不用哨兵的方式,如当left或right有一方
// 已经遍历到尽头时,直接将另一方剩余的数组元素直接复制到a对应的位置。
left[i] = Integer.MAX_VALUE;
right[j] = Integer.MAX_VALUE;
i = j = 0;
for (int k = p; k < r+1; k++) {
if (left[i] < right[j]) {
a[k] = left[i];
i++;
} else {
a[k] = right[j];
j++;
}
}
System.out.println("merge counter: " + (++mergeCalledCounter));
printArray(s);
}
static void mergeSort(int[] a, int p, int r) {
if (p < r) {
int q;
if ((p+r)%2 != 0) {
q = (p+r-1)/2;
} else {
q = (p+r)/2;
}
mergeSort(a, p, q);
mergeSort(a, (q+1), r);
merge(a, p, q, r);
}
}
private static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
printArray(s);
mergeSort(s, 0, s.length-1);
}
}
运行结果:
2 1 10 20 3 2 44 23 7 6 84 100
merge counter: 1
1 2 10 20 3 2 44 23 7 6 84 100
merge counter: 2
1 2 10 20 3 2 44 23 7 6 84 100
merge counter: 3
1 2 10 3 20 2 44 23 7 6 84 100
merge counter: 4
1 2 10 2 3 20 44 23 7 6 84 100
merge counter: 5
1 2 2 3 10 20 44 23 7 6 84 100
merge counter: 6
1 2 2 3 10 20 23 44 7 6 84 100
merge counter: 7
1 2 2 3 10 20 7 23 44 6 84 100
merge counter: 8
1 2 2 3 10 20 7 23 44 6 84 100
merge counter: 9
1 2 2 3 10 20 7 23 44 6 84 100
merge counter: 10
1 2 2 3 10 20 6 7 23 44 84 100
merge counter: 11
1 2 2 3 6 7 10 20 23 44 84 100
课后习题2.3-7
描述一个运行时间为Θ(nlgn)的算法,给定n个整数的集合S和另一个整数x,该算法能确定S中是否存在两个其和刚好为x的元素。
伪代码
1: 先用归并排序算法将集合S排好序,其运行时间 Θ(n lg(n))
2: i = 1
3: j = n
4: while i < j do
5: if A[i] + A[j] = x then
6: return true
7: end if
8: else if A[i] + A[j] < x then
9: i = i + 1
10: end else if
11: else A[i] + A[j] > x then
12: j = j - 1
13: end else
14: end while
15: return false
第2-15步的运行时间为O(n) ,相对于Θ(n lg(n)),O(n)可被忽略,所以整个算法的运行时间为Θ(n lg(n))。
java代码
public class Test_2_3_7 {
public static void main(String[] args) {
int[] s = {10,3,4,2,5,9,4,7,6,8};
final int bingo = 15;
int i = 0;
int j = s.length - 1;
int tmpSum;
s = MergeSort.mergeSort(s, i, j); // 运用归并排序算法将数组s中的元素从小到大排序
while (i < j) {
tmpSum = s[i] + s[j];
if (tmpSum == bingo) {
System.out.println("i:" + i + " | j:" + j);
System.out.println("s[i]:"+s[i] + " | " + "s[j]:"+s[j]);
return;
} else if (tmpSum < bingo) {
i++;
} else {
j--;
}
}
System.out.println("can't find i and j");
}
}