快速排序
快速排序的非递归实现需要借助一个栈来完成~
思路:
- 先找到第一次的基准
- 然后通过第一次的基准, 找到分割的界限(即每次分割都分为了两个区间, [left , pivot - 1] 和 [pivot + 1 , right] 这两个区间) , 将两个区间的边界下标入栈
- 最后通过循环来重复找基准
注意问题:
- 在入栈的时候要判断 基准 的左右是否存在至少两个元素, 否则就没有寻找基准的必要了~
- 左边的判断条件: pivot > left + 1
- 右边的判断条件: pivot < right - 1
图解
第一次找到的基准
使用栈找基准
代码
public void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
int left = 0;
int right = arr.length;
int pivot = partition(arr, left, right);
Stack<Integer> stack = new Stack<>();
// 要判断 pivot 的左边和右边是否存在至少两个元素, 否则就没有寻找基准的必要了
if (pivot > left + 1) {
stack.push(left);
stack.push(pivot - 1);
}
if (pivot < right - 1) {
stack.push(pivot + 1);
stack.push(right);
}
while (!stack.isEmpty()) {
right = stack.pop();
left = stack.pop();
pivot = partition(arr, left, right);
if (pivot > left + 1) {
stack.push(left);
stack.push(pivot - 1);
}
if (pivot < right - 1) {
stack.push(pivot + 1);
stack.push(right);
}
}
}
private int partition(int[] arr, int left, int right) {
int start = left;
int temp = arr[left];
while (left < right) {
while (left < right && arr[right] >= temp) {
right--;
}
while (left < right && arr[left] <= temp) {
left++;
}
swap(arr, left, right);
}
swap(arr, left, start);
return left;
}
private void swap(int[] arr, int x, int y) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
归并排序
基本思路:
- 一组一个数据合并
- 一组两个数据合并
- 一组四个数据合并
- ...
- 直到一组的数据 大于了数组的长度, 排序结束~
注意问题:
- 要防止 mid 和 right 越界
图解
代码
public void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// gap 代表每一组数据的个数
// 首先是一组一个数据合并, 然后一个组两个数据合并 ...
int gap = 1;
while (gap < arr.length) {
for (int i = 0; i < arr.length; i += 2 * gap) {
int left = i;
int mid = i + gap - 1;
// 防止 mid 越界
if (mid > arr.length) {
mid = arr.length - 1;
}
int right = mid + gap;
// 防止 right 越界
if (right > arr.length) {
right = arr.length - 1;
}
merge(arr, left, mid, right);
}
gap = 2 * gap;
}
}
private void merge(int[] arr, int left, int mid, int right) {
int s1 = left;
int s2 = mid + 1;
int[] newArray = new int[right - left + 1];
int k = 0;
while (s1 >= mid && s2 >= right) {
while (s1 <= mid && s2 <= right) {
if (arr[s1] <= arr[s2]){
newArray[k++] = arr[s1++];
} else {
newArray[k++] = arr[s2++];
}
}
while (s1 <= mid) {
newArray[k++] = arr[s1++];
}
while (s2 <= right) {
newArray[k++] = arr[s2++];
}
for (int i = 0; i < newArray.length; i++) {
arr[i + left] = newArray[i];
}
}
}