快速排序
分析
快速排序简单来说就是分治递归。
首先将一个值确定为中枢值pivot(一般取第一个),然后小于pivot的放左边,大于pivot的放右边。
接着再对左右两边区间进行同样的操作。
代码
public class QuickSort {
/**
* 快速排序的入口方法。
*
* @param nums 要排序的数组
*/
public void quickSort(int[] nums) {
quickSort(nums, 0, nums.length - 1); // 从数组的第一个元素开始排序
}
/**
* 快速排序的递归实现。
*
* @param nums 要排序的数组
* @param left 子数组的起始索引
* @param right 子数组的结束索引
*/
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); // 递归地对右侧子数组进行排序
}
}
/**
* 分区函数,用于将小于基准值的元素移动到左边,大于基准值的元素移动到右边。
*
* @param nums 要排序的数组
* @param left 子数组的起始索引
* @param right 子数组的结束索引
* @return 分区后基准元素的位置
*/
private int partition(int[] nums, int left, int right) {
int pivot = nums[left]; // 选择第一个元素作为基准值
int i = left; // 设置一个指针 i 指向基准值
for (int j = left + 1; j <= right; j++) { // 从第二个元素开始遍历
if (nums[j] < pivot) { // 如果当前元素小于基准值
swap(nums, ++i, j); // 将当前元素交换到比基准值小的区域
}
}
swap(nums, left, i); // 最后将基准值放到正确的位置上
return i; // 返回基准值的位置
}
/**
* 交换数组中的两个元素。
*
* @param nums 要交换元素的数组
* @param i 第一个元素的索引
* @param j 第二个元素的索引
*/
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
归并排序
分析
快速排序是先划分区域再接着往下拆,而归并排序就是往下一直拆,合并的时候再排序。
代码
class MergeSort {
/**
* 归并排序的入口方法。
*
* @param nums 要排序的数组
*/
public void mergeSort(int[] nums) {
mergeSort(nums, 0, nums.length - 1); // 从数组的第一个元素开始排序
}
/**
* 归并排序的递归实现。
*
* @param nums 要排序的数组
* @param left 子数组的起始索引
* @param right 子数组的结束索引
*/
public void mergeSort(int[] nums, int left, int right) {
if (left < right) { // 当子数组至少有两个元素时才进行排序
int center = (left + right) / 2; // 计算中间位置
mergeSort(nums, left, center); // 对左半边进行排序
mergeSort(nums, center + 1, right); // 对右半边进行排序
merge(nums, left, center, right); // 合并两个已排序的子数组
}
}
/**
* 合并两个已排序的子数组。
*
* @param nums 原数组
* @param left 左子数组的起始索引
* @param center 中间索引,左子数组的最后一个元素的下一个索引
* @param right 右子数组的结束索引
*/
public void merge(int[] nums, int left, int center, int right) {
int len = right - left + 1; // 计算临时数组的长度
int[] tmp = new int[len]; // 创建临时数组用于合并
int index = 0; // 临时数组的索引
int start1 = left; // 左子数组的起始索引
int start2 = center + 1; // 右子数组的起始索引
// 合并两个子数组中的元素
while (start1 <= center && start2 <= right) {
if (nums[start1] < nums[start2]) { // 如果左子数组的当前元素小于右子数组的当前元素
tmp[index++] = nums[start1++]; // 将左子数组的当前元素放入临时数组,并移动左子数组的索引
} else {
tmp[index++] = nums[start2++]; // 否则将右子数组的当前元素放入临时数组,并移动右子数组的索引
}
}
// 处理剩余的元素
while (start1 <= center) { // 如果左子数组还有剩余元素
tmp[index++] = nums[start1++]; // 将剩余元素依次放入临时数组
}
while (start2 <= right) { // 如果右子数组还有剩余元素
tmp[index++] = nums[start2++]; // 将剩余元素依次放入临时数组
}
// 将临时数组中的元素复制回原数组
index = 0;
while (index < len) {
nums[left + index] = tmp[index]; // 将临时数组中的元素复制回原数组
index++;
}
}
}
(by 归忆)