当前位置: 首页 > news >正文

数据结构-排序(2)

一、堆排序 (借助树)

1.利用完全二叉树构建大顶堆
2.堆顶元素和堆底元素进行交换,堆底元素不再参与构建,剩余元素继续构建大顶堆

3.时间复杂度  O(nlogn)

1.完全二叉树:按照从上到下,从左到右的顺序进行排序

2.大顶堆: 任何一个节点值大于等于左右孩子,根节点一定是最大值

arr[i]的左孩子 arr[2i+1]           要求条件: arr[i]>= arr[2i+1]&&

 arr[i]的右孩子 arr[2i-2]                                arr[i]>=arr[2i-2]

3.构建大顶堆:

第一大步:

1. 从后往前对每个数据依次进行检测调整
2. 定义 parent 游标指向要检测的节点
3. 定义 parent 的左孩子,判断 child 是否为空(有孩子一定会有左孩子)
4. 如果 child 为空,则 parent 符合大顶堆
5. 如果 child 不为空,判断 parent 有没有右孩子,child 指向左右孩子的最大值。
6. 父子节点进行比较,如果父节点的值大,则符合大顶堆,继续向前检测。
7. 如果父节点的值小,则不符合大顶堆,父子节点进行交换。
8. parent 指向 child, child 指向左右孩子的最大值。直到 child 为空或者父节点的值大。

第二大步:

 1.只有堆顶变了,只维护堆顶就可以,做到堆顶最大

package com.pcby.demo;//堆排序
import java.util.Arrays;
/*1.利用完全二叉树构建大顶堆* 2.堆顶元素和堆底元素进行交换,堆底元素不再参与构建,剩余元素继续构建大顶堆*/public class HeapSort {public static void main(String[] args) {int[] arr= {5,7,4,2,0,3,1,6};sort(arr);System.out.println(Arrays.toString(arr));}// 排序public static void sort(int[] arr){// 第一大步for (int i = arr.length - 1; i >= 0; i--) {adjust(arr, i, arr.length);}// 第二大步for (int i = arr.length - 1; i >= 0; i--) {int temp = arr[0];arr[0] = arr[i];arr[i] = temp;adjust(arr, 0, i);}}// 维护public static void adjust(int[] arr, int parent, int length) {int child = 2 * parent + 1;while (child < length) {// 定义右孩子int rchild = child + 1;if (rchild < length && arr[rchild] > arr[child]) {child++;} // child 指向了左右孩子的最大值// 父子节点进行比较,父节点要大if (arr[parent] < arr[child]) {// 父子节点进行交换int temp = arr[parent];arr[parent] = arr[child];arr[child] = temp;// 父节点指向 child, child 指向左右孩子最大值parent = child;child = 2 * child + 1;} else {break;}}}
}

每一步思路:
1. 定义数组并调用排序函数:
在  main  方法中,定义一个数组  arr ,其元素为  {5,7,4,2,0,3,1,6} 。
调用  sort  方法对数组进行堆排序。
输出排序后的数组。
2. 排序方法(sort 方法):
第一大步(构建初始大顶堆):
从数组的最后一个元素开始,逐个向前调整,确保每个父节点都大于其子节点。
调用  adjust  方法对每个元素进行调整。
第二大步(排序过程):
将堆顶元素(最大值)与堆底元素交换,使最大值位于数组末尾。
堆的大小减 1(通过调整  length  参数实现),对剩余元素重新调整为大顶堆。
重复上述交换和调整过程,直到堆的大小为 1。
3. 调整堆结构(adjust 方法):
初始化父节点和左孩子节点的位置。
在循环中,检查右孩子节点是否存在且是否大于左孩子节点,将  child  指向左右孩子中较大的那个。
如果父节点小于当前  child  节点,交换它们的位置。
更新父节点和孩子节点的位置,继续调整子树,直到父节点大于等于孩子节点或孩子节点超出堆的范围。

 二、基数排序(借助桶)

不能排负值,先排序个位,十位,百位

1.先建立0-9九个桶

2.看各个数字个位数都是多少,是多少放在哪个桶里

3.放好后从0号桶开始取数字,取出来,在排序十位,同理排序百位

 
package com.pcby.demo;import java.util.Arrays;public class Radix {public static void main(String[] args) {int[] arr = {5,14,20,125,362,61,94,4,12,1002,54,99,87,89};sort(arr);System.out.println(Arrays.toString(arr));}public static void sort(int[] arr) {// 找最大值int max = arr[0];for (int i = 0; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}// 最大值的位数int len = (max + "").length();// 声明 0-9 十个桶int[][] bucket = new int[10][arr.length];// 桶记录工具int[] elementCount = new int[10];int n = 1;// 循环放入取出for (int num = 0; num < len; num++) {// 放入for (int i = 0; i < arr.length; i++) {// 放到哪个桶 余数int element = arr[i] / n % 10;int count = elementCount[element];bucket[element][count] = arr[i];// 桶记录 +1elementCount[element]++;}// 取出int index = 0;for (int i = 0; i < elementCount.length; i++) {if (elementCount[i] > 0) {for (int j = 0; j < elementCount[i]; j++) {arr[index] = bucket[i][j];index++;}elementCount[i] = 0;}}n = n * 10;}}
}

三、快速排序

待排序数组的第一个作为基准数;

定义游标 j 从后往前,找比基准数小的值,找到后停下;

定义游标 i 从前往后,找比基准数大的值,找到后停下;

i j 指向的数据交换 j 继续找比基准数小的,i 继续找比基准数大的,直到 i j 相遇 基准数和相遇位置交换,基准数到达正确位置;

以基准数为起始点,拆分成左右两部分,重复上述所有,直到数据独立

时间复杂度: O(n log n)

import java.util.Arrays;public class QuickSort {public static void main(String[] args) {int[] arr = {5, 7, 4, 2, 0, 3, 1, 6};sort(arr, 0, arr.length - 1);System.out.println(Arrays.toString(arr));}public static void sort(int[] arr, int left, int right) {if (left >= right) {return;}int base = arr[left];int j = right;int i = left;while (i != j) {while (arr[j] >= base && i != j) {j--;}while (arr[i] <= base && i != j) {i++;}int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}arr[left] = arr[i];arr[i] = base;sort(arr, left, i - 1);sort(arr, i + 1, right);}
}

四、归并排序

即将数组不断拆分为小数组,对小数组进行排序后再合并成大数组。先拆分再合并,在合并的过程中通过临时空间进行排序。

空间复杂度:O(n)

​
package com.qcbj.sort;
import java.util.Arrays;public class MergeSort {public static void main(String[] args) {int[] arr = {5, 7, 4, 2, 0, 3, 1, 6};split(arr, 0, arr.length - 1);System.out.println(Arrays.toString(arr));}public static void split(int[] arr, int left, int right) {if (left == right) {return;}int mid = (left + right) / 2;split(arr, left, mid);split(arr, mid + 1, right);merge(arr, left, mid, right);}public static void merge(int[] arr, int left, int mid, int right) {int s1 = left;int s2 = mid + 1;int[] temp = new int[right - left + 1];int index = 0;while (s1 <= mid && s2 <= right) {if (arr[s1] <= arr[s2]) {temp[index] = arr[s1];index++;s1++;} else {temp[index] = arr[s2];index++;s2++;}}while (s1 <= mid) {temp[index] = arr[s1];index++;s1++;}while (s2 <= right) {temp[index] = arr[s2];index++;s2++;}for (int i = 0; i < temp.length; i++) {arr[left + i] = temp[i];}}
}​

http://www.dtcms.com/a/326524.html

相关文章:

  • 嵌入式 - Linux软件编程:标准IO
  • 文件夹生成器,一键批量生成,效率提升!
  • 1.Apollo Planning 模块总结
  • 一键生成AI视频!Spring Cloud微服务架构的AgentAlVideo平台开源啦!
  • 内存问题排查工具ASan初探
  • 【liunx】web高可用---nginx
  • AR 智能眼镜:从入门到未来
  • DDIA第五章:复制
  • PCB批量线路板厂家有哪些?
  • LAMPLNMP 最佳实践
  • Ubuntu 22.04 离线环境下 Python 包与 FFmpeg 安装全攻略​
  • 嵌入式Linnux学习 -- 软件编程2
  • linux下部署 dify,并配置本地ollama大模型
  • 【排序算法】⑤冒泡排序
  • Java学习 -- 可变参数与Collections工具类
  • docker安装Engine stopped
  • AI自动生成接口测试脚本全流程
  • 当AI重塑世界:普通人如何成为“主动进化者”?
  • 在 .NET Core 5.0 中启用 Gzip 压缩 Response
  • ECCV 2024 论文解读丨具身智能、机器人研究最新突破创先点分享合集
  • MCU中的存储器映射(Memory Map)
  • 登录系统英文使用 Sign In?Log In?还是 Log On?
  • Windows Server 2022域控制器部署与DNS集成方案
  • 大模型工程问题
  • Python网络爬虫(一) - 爬取静态网页
  • 打烊:餐厅开业前的“压力测试”
  • nginx 设置二级目录-实战
  • P1967 [NOIP 2013 提高组] 货车运输【题解】
  • 当智慧在腕间流转:一场无声的协同交响
  • haproxy 2.4.x, /metrics 取数据遇到的问题