归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
算法核心逻辑如下
mid = (left + right) / 2
来进行。private static void MergeSort(int[] arr,int left,int right,int []temp){
if(left
算法分析:稳定时间复杂度的一个算法,但是会造成额外的空间开销int [] temp
快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法核心逻辑
// 快速排序
public static void quickSort(int[] arr, int left, int right) {
if (left >= right) {
return;
}
int pivot = arr[left]; // 基准元素
int i = left, j = right;
while (i < j) {
// 从右边开始,找到小于基准的元素
while (i < j && arr[j] >= pivot) {
j--;
}
// 从左边开始,找到大于基准的元素
while (i < j && arr[i] <= pivot) {
i++;
}
// 交换两个元素
if (i < j) {
swap(arr, i, j);
}
}
// 将基准元素放到正确位置
arr[left] = arr[i];
arr[i] = pivot;
// 递归排序左右部分
quickSort(arr, left, i - 1);
quickSort(arr, i + 1, right);
}
// 交换数组中的两个元素
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
get不到这段代码逻辑的问问GPT就好了~
算法分析:快速排序适合大数据量并且数据不均匀的情况下用, 通过选择一个合理的分区点(pivot),每次都能将数据集分成相对均匀的两部分,这样快速排序能够利用分治思想高效地排序 。并且不用额外内存空间(原地移动)
原理:堆排序是一种基于完全二叉树的排序算法,时间复杂度为 O(n log n),是一种不稳定的排序方法。堆排序的基本思想是:首先将待排序数组构建成一个大根堆(或小根堆),然后将堆顶元素与最后一个元素交换,接着重新调整堆结构,使得新的堆顶元素仍然是最大(或最小)的,再重复这一过程直到所有元素都排序完毕。
算法核心逻辑
heapSort
方法的第一个 for
循环中,调用 adjustHeap
函数将数组调整成最大堆。这里从 arr.length / 2 - 1
开始向前调整,确保每个节点的子树都符合最大堆的性质。for
循环中,堆顶元素(即 arr[0]
)和当前堆的最后一个元素交换,这使得最大值被放置到数组的末端。adjustHeap
来重新调整堆顶元素,使得剩余的元素仍然满足堆的性质。这里的 adjustHeap
主要负责维护堆的结构。for
循环会继续执行,直到数组的所有元素都被排好序为止。每次 adjustHeap
都是对堆顶元素进行调整,确保最大堆的性质持续保持。 public static void heapSort(int[] arr) {
int temp = 0;
// 1. 构建最大堆
for (int i = arr.length / 2 - 1; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
// 2. 将最大堆的根元素与末尾元素交换,然后重新调整堆
for (int j = arr.length - 1; j > 0; j--) {
// 交换根元素和当前末尾元素
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
// 重新调整堆,排除已排好序的部分
adjustHeap(arr, 0, j);
}
}
// 调整堆,使得以i为根节点的子树满足大根堆的性质
public static void adjustHeap(int[] arr, int i, int length) {
int temp = arr[i]; // 保存父节点的值
// 从i的左子节点开始
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
// 如果右子节点比左子节点大,则选择右子节点
if (k + 1 < length && arr[k] < arr[k + 1]) {
k++;
}
// 如果子节点比父节点大,交换它们
if (arr[k] > arr[i]) {
arr[i] = arr[k];
i = k; // i移到交换后的子节点位置
} else {
break; // 如果已经满足堆的性质,就不需要继续调整
}
}
// 将父节点的值放到新的位置
arr[i] = temp;
}
算法分析:
桶排序的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序
算法核心逻辑伪代码
1. 初始化空桶数组bucket
2. 遍历待排序数组arr,将每个元素按照某种映射规则分配到对应的桶中
bucket[floor(arr[i]/bucketSize)] += arr[i]
3. 遍历桶数组bucket,对每个非空桶内部进行排序
for j = 0 to bucket.length-1 do
if bucket[j] is not empty then
sort(bucket[j])
4. 将各个桶内部排序后的数据合并到待排序数组arr中
index = 0
for j = 0 to bucket.length-1 do
if bucket[j] is not empty then
for k = 0 to bucket[j].length-1 do
arr[index] = bucket[j][k]
index++
5. 返回排好序的数组arr
public static void bucketSort(int[] arr, int bucketSize) {
if (arr.length == 0) {
return;
}
// 寻找数组中的最大值和最小值
int minValue = arr[0];
int maxValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < minValue) {
minValue = arr[i];
} else if (arr[i] > maxValue) {
maxValue = arr[i];
}
}
// 计算桶的数量
int bucketCount = (maxValue - minValue) / bucketSize + 1;
ArrayList> buckets = new ArrayList<>(bucketCount);
for (int i = 0; i < bucketCount; i++) {
buckets.add(new ArrayList<>());
}
// 将数组中的元素分配到各个桶中
for (int value : arr) {
int bucketIndex = (value - minValue) / bucketSize;
buckets.get(bucketIndex).add(value);
}
// 对每个非空的桶内部进行排序
int index = 0;
for (ArrayList bucket : buckets) {
if (!bucket.isEmpty()) {
Collections.sort(bucket); // 这里使用了Java自带的排序方法
for (int value : bucket) {
arr[index++] = value;
}
}
}
}
算法分析
桶排序的时间复杂度可以达到O(n),但是桶排序对传入的数据有要求,需要传入数据均匀分布的情况下才能达到O(n)