三大排序算法总结
三大排序算法: 快速排序, 堆排序, 归并排序
912. 排序数组
冒泡排序: 10个数字,需要9次循环,每次排序出一个最大值,最后一个元素自动排序.
- 快速排序
建立基准pivot,根据基准左右分割进行排序 - 堆排序
构建二叉树,保持父节点数值总是大于等于子节点的数值, 可以直接使用原数组构建树结构,left = 2 * i +1; right = 2 * i + 2; 索引i的左右孩子节点的索引关系 - 归并排序:
分治法, (将序列划分两部分再将每一部分排序), 将每一部分一直划分, 直到只有一个元素为止, 两个各一个元素进行行合并=> 形成有序序列, 再将有序序列合并, 排序成功,
分治法: 使用后序递归思路, 先分, 对根节点进行处理
Java代码实现
// 快速排序
class Solution {
// 比较: 比pivot小, 交换到前面, 交换pivot, 返回pivot位置
private int partition(int[] nums, int left, int right) {
int pivot = left;
int index = pivot + 1;
for (int i = index; i < right + 1; i++) {
if (nums[i] < nums[pivot]) {
int temp = nums[i];
nums[i] = nums[index];
nums[index] = temp;
index++;
}
}
int temp = nums[index - 1];
nums[index - 1] = nums[pivot];
nums[pivot] = temp;
return index - 1;
}
// 先比较, 再划分(先序遍历过程)
private void quickSort(int[] nums, int left, int right) {
if (left < right) {
int pivot = partition(nums, left, right);
quickSort(nums, left, pivot - 1);
quickSort(nums, pivot + 1, right);
}
}
public int[] sortArray(int[] nums) {
int left = 0;
int right = nums.length - 1;
quickSort(nums, left, right);
return nums;
}
}
// 堆排序
static class Solution2 {
// 调整所有的父节点(验证是否>=子节点), 逆向遍历, nums.length / 2
private void buildHeap(int[] nums) {
for (int i = (nums.length / 2) - 1; i >= 0; i--) {
adjustHeap(nums, nums.length - 1, i);
}
}
// 调整堆: 最大节点换到父节点上, 后序递归交换
private void adjustHeap(int[] nums, int rightIndex, int index) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int largestIndex = index;
if (left <= rightIndex && nums[left] > nums[largestIndex]) {
largestIndex = left;
}
if (right <= rightIndex && nums[right] > nums[largestIndex]) {
largestIndex = right;
}
if (largestIndex != index) {
int temp = nums[index];
nums[index] = nums[largestIndex];
nums[largestIndex] = temp;
adjustHeap(nums, rightIndex, largestIndex);
}
}
// 堆排序: 不断交换根节点
private void heapSort(int[] nums) {
int rightIndex = nums.length - 1;
buildHeap(nums);
for (int i = 0; i < nums.length; i++) {
// 交换根节点nums[0], 和尾节点 nums[right]; 删除尾节点(right--), 调整堆
int temp = nums[0];
nums[0] = nums[rightIndex];
nums[rightIndex] = temp;
rightIndex--;
adjustHeap(nums, rightIndex, 0);
}
}
public int[] sortArray(int[] nums) {
heapSort(nums);
return nums;
}
}
// 归并排序
class Solution3 {
// 归并排序, 先划分再排序(后序遍历过程), 回到根节点再处理: 0, 1, 2
private int[] mergeSort(int[] nums) {
if (nums.length <= 1) return nums;
int mid = nums.length / 2;
// [0,mid), [mid, endIndex]
int[] left = mergeSort(Arrays.copyOfRange(nums, 0, mid));
int[] right = mergeSort(Arrays.copyOfRange(nums, mid, nums.length));
return merge(left, right);
}
// 将有序序列left和right进行合并, 长度会发生变化所以需要增加空间
private int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
int i = 0, j = 0;
for (int rIndex = 0; rIndex < result.length; rIndex++) {
if (i >= left.length) {
result[rIndex] = right[j++];
} else if (j >= right.length) {
result[rIndex] = left[i++];
} else if (left[i] < right[j]) {
result[rIndex] = left[i++];
} else {
result[rIndex] = right[j++];
}
}
return result;
}
public int[] sortArray(int[] nums) {
nums = mergeSort(nums);
return nums;
}
}
参考