七日算法先导(六)——堆排序,桶排序
作者:秋名山码民
- 2022 年 8 月 09 日 陕西
本文字数:2798 字
阅读完需:约 9 分钟
前言所学
前面我们学习了归并,希尔俩个排序,下面由这张图来总结一下八大排序
可能有的小伙伴会说,学这些排序有什么用,平时开发也用不到,但是我的理解是这样的:
锻炼思维,排序中蕴含的思维很多,双指针,递归,分治等等
普及常识性问题
面试,区分人才
堆排序
堆的结构可以分为大根堆和小根堆,是一个完全二叉树,而堆排序是根据堆的这种数据结构设计的一种排序,下面先来看看什么是大根堆和小根堆
大顶堆,小顶堆
当所有根节点的值,都大于它子节点的值,我们称为大顶(根)堆
当所有根节点的值,都小于它子节点的值,我们称为小顶(根)堆
思路及动画演示
代码实现
public class HeapSort extends BaseSort { public static void main(String[] args) { HeapSort sort = new HeapSort(); sort.printNums(); } @Override protected void sort(int[] nums) { if (nums == null || nums.length < 2) { return; } heapSort(nums); } private void heapSort(int[] nums) { if (nums == null || nums.length < 2) { return; } //构建大根堆 createTopHeap(nums); int size = nums.length; while (size > 1) { //大根堆的交换头尾值,固定最大值在末尾 swap(nums, 0, size - 1); //末尾的索引值往左减1 size--; //重新构建大根堆 updateHeap(nums, size); } } private void createTopHeap(int[] nums) { for (int i = 0; i < nums.length; i++) { //当前插入的索引 int currIndex = i; //父节点的索引 int parentIndex = (currIndex - 1) / 2; //如果当前遍历的值比父节点大的话,就交换值。然后继续往上层比较 while (nums[currIndex] > nums[parentIndex]) { //交换当前遍历的值与父节点的值 swap(nums, currIndex, parentIndex); //把父节点的索引指向当前遍历的索引 currIndex = parentIndex; //往上计算父节点索引 parentIndex = (currIndex - 1) / 2; } } } private void updateHeap(int[] nums, int size) { int index = 0; //左节点索引 int left = 2 * index + 1; //右节点索引 int right = 2 * index + 2; while (left < size) { //最大值的索引 int largestIndex; //如果右节点大于左节点,则最大值索引指向右子节点索引 if (right < size && nums[left] < nums[right]) { largestIndex = right; } else { largestIndex = left; } //如果父节点大于最大值,则把父节点索引指向最大值索引 if (nums[index] > nums[largestIndex]) { largestIndex = index; } //如果父节点索引指向最大值索引,证明已经是大根堆,退出循环 if (largestIndex == index) { break; } //如果不是大根堆,则交换父节点的值 swap(nums, largestIndex, index); //把最大值的索引变成父节点索引 index = largestIndex; //重新计算左节点索引 left = 2 * index + 1; //重新计算右节点索引 right = 2 * index + 2; } } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }}
复制代码
桶排序
过程
排序过程:(1)设置一个定量的数组当作空桶子;(2)寻访序列,并且把记录一个一个放到对应的桶子去;(3)对每个不是空的桶子进行排序。(4)从不是空的桶子里把项目再放回原来的序列中。
代码实现
public class BucketSort extends BaseSort { public static void main(String[] args) { BucketSort sort = new BucketSort(); sort.printNums(); } @Override protected void sort(int[] nums) { if (nums == null || nums.length < 2) { return; } bucketSort(nums); } public void bucketSort(int[] nums) { if (nums == null || nums.length < 2) { return; } //找出最大值,最小值 int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for (int num : nums) { min = Math.min(min, num); max = Math.max(max, num); } int length = nums.length; //桶的数量 int bucketCount = (max - min) / length + 1; int[][] bucketArrays = new int[bucketCount][]; //遍历数组,放入桶内 for (int i = 0; i < length; i++) { //找到桶的下标 int index = (nums[i] - min) / length; //添加到指定下标的桶里,并且使用插入排序排序 bucketArrays[index] = insertSortArrays(bucketArrays[index], nums[i]); } int k = 0; //合并全部桶的 for (int[] bucketArray : bucketArrays) { if (bucketArray == null || bucketArray.length == 0) { continue; } for (int i : bucketArray) { //把值放回到nums数组中 nums[k++] = i; } } } //每个桶使用插入排序进行排序 private int[] insertSortArrays(int[] arr, int num) { if (arr == null || arr.length == 0) { return new int[]{num}; } //创建一个temp数组,长度是arr数组的长度+1 int[] temp = new int[arr.length + 1]; //把传进来的arr数组,复制到temp数组 for (int i = 0; i < arr.length; i++) { temp[i] = arr[i]; } //找到一个位置,插入,形成新的有序的数组 int i; for (i = temp.length - 2; i >= 0 && temp[i] > num; i--) { temp[i + 1] = temp[i]; } //插入需要添加的值 temp[i + 1] = num; //返回 return temp; }}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 6
秋名山码民
关注
卷不死,就往…… 2021.10.19 加入
2019NOIP退役成员,华为云享专家,阿里云专家博主,csdn博主,努力进行算法分享,有问题欢迎私聊










评论