归并排序
思路:
- 设置step步长 将数组按步长划分 比如arr[0,1,2,3,4] 开始step = 1;
- 第一个左组[0] 和 第一个右组[1] 进行merge操作;第二个左组[2] 和 第二个右组[3] 进行merge操作;剩下的不足以划分
- 将step * 2 , 开始merge新的左组 和 右组,等到step = 4时 此时左组[0,1,2,3] 右组[4] 进行merge操作
- 判断step >= N 就可以退出循环
public static void mergeSort2(Integer[] arr) {
if (arr == null || arr.length < 2) {
return;
}
int N = arr.length;
//步长
int step = 1;
while (step < N) {
int L = 0;
while (L < N) {
//判断最后的数据是否能凑成左组和右组,如果 N - L < step 说明凑不到右组
if (step >= N - L) {
break;
}
//计算中间位置
int M = L + step - 1;
//计算右组位置 判断右组是否满足step个元素 不足R = M + (N - M - 1)
int R = M + Math.min(step, N - M - 1);
merge(arr, L, M, R);
L = R + 1;
}
//不能判断为step >= N /2 , 因为是向下取整,如果arr长度17 步长=8的时候就会退出,最后的16步长没有merge
if (step > N / 2) {
break;
}
step <<= 1;
}
}
快排
快排的思想就是递归+分治;将数组划分为小于和大于选定元素的区域,当最后局部的左组和右组是有序的,整体就是有序的。
分割数组
问题描述:
将数组分割成<=num 和 > num的两部分
public static void splitNum1(Integer[] arr) {
int lessEqualR = -1;
int index = 0;
int N = arr.length;
while (index < N) {
if (arr[index] <= arr[N - 1]) {
exec(arr, ++lessEqualR, index++);
} else {
index++;
}
}
}
分割数组2
问题描述:将数组分割成<num、 =num 和 > num的三部分
public static void splitNum2(Integer[] arr) {
int N = arr.length;
int lessR = -1;
int moreL = N - 1;
int index = 0;
// arr[N-1]
while (index < moreL) {
if (arr[index] < arr[N - 1]) {
exec(arr, ++lessR, index++);
} else if (arr[index] > arr[N - 1]) {
exec(arr, --moreL, index);
} else {
index++;
}
}
exec(arr, moreL, N - 1);
}
递归版本-快排
// arr[L...R]范围上,拿arr[R]做划分值,
// L....R < = >
public static int[] partition(Integer[] arr, int L, int R) {
int lessR = L - 1;
int moreL = R;
int index = L;
while (index < moreL) {
if (arr[index] < arr[R]) {
exec(arr, ++lessR, index++);
} else if (arr[index] > arr[R]) {
exec(arr, --moreL, index);
} else {
index++;
}
}
exec(arr, moreL, R);
return new int[] { lessR + 1, moreL };
}
public static void process(Integer[] arr, int L, int R) {
if (L >= R) {
return;
}
int[] equalE = partition(arr, L, R);
process(arr, L, equalE[0] - 1);
process(arr, equalE[1] + 1, R);
}
public static void quickSort1(Integer[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
}
非递归版本-快排
/**
* 需要处理的小任务:也就是需要划分数组
*/
public static class Job {
public int L;
public int R;
public Job(int left, int right) {
L = left;
R = right;
}
}
public static void quickSort2(Integer[] arr) {
if (arr == null || arr.length < 2) {
return;
}
Stack<Job> stack = new Stack<>();
stack.push(new Job(0, arr.length - 1));
while (!stack.isEmpty()) {
Job cur = stack.pop();
int[] equals = partition(arr, cur.L, cur.R);
if (equals[0] > cur.L) { // 有< 区域
stack.push(new Job(cur.L, equals[0] - 1));
}
if (equals[1] < cur.R) { // 有 > 区域
stack.push(new Job(equals[1] + 1, cur.R));
}
}
}