三、详解桶排序以及排序内容大总结

详解桶排序以及排序内容大总结

文章目录

  • 详解桶排序以及排序内容大总结
      • 堆的操作(大)
        • heapinsert --- 调整成大根堆
        • heapify --- 移除原根节点后,继续调整成大根堆
        • 堆中某个位置的数值发生改变
    • 堆排序
      • 优化
    • 堆练习
    • 比较器
    • 桶排序
      • 基数排序

注:堆是一种特殊的二叉树

堆分为大根堆(以某一节点为根节点的整棵树中最大值为该节点)和小根堆(以某一节点为根节点的整棵树中最小值为该节点)

在这里插入图片描述

堆的操作(大)

heapinsert — 调整成大根堆

假设一个用户不断地给出数,程序拿到数字并将在此之前的所有数字调整成大根堆

  1. 找父节点(i-1)/2进行比较,比父节点大则交换位置

代码实现:

 /*** 调整过程:某个数正处在index的位置,不断往上调整位置时** 新节点比自己的父节点大,位置需要置换* 置换以后新节点处于父节点位置,下标需要改变* @param arr* @param index*/public static void heapInsert(int[]arr,int index){//while停止条件://1:来到了一个合适的位置,比自己的父亲节点小,不需要再调整//2:来到了根节点,根节点下标为0,(0-1)/2==0,自己不会比自己大,while停止while(arr[index] > arr[(index-1)/2]){//置换swap(arr,index,(index-1)/2);//改变该节点位置index = (index-1)/2;}}
heapify — 移除原根节点后,继续调整成大根堆

假设用户停止抛出数字,让程序返回在此之前的所有数中的最大值,并且将剩下的数再次调整成为大根堆

  1. 返回下标为0的数字,即为最大值
  2. 将堆中的最后一个数的位置调换到根节点的位置(用root标记),数组长度-1,开始调整
  3. 调整步骤:在root节点的左孩子和右孩子之中选择一个最大值,与root进行比较,root比较小的话则调换位置;继续上述调整步骤,知道root节点比自己的左右孩子都大,或者没有左右孩子时

代码实现:

	/*** 剔除最大值后,对剩下的节点调整成大根队* @param arr* @param index   初始index  可以从任何一个位置往下调整* @param heapSize   堆的大小*/public static void heapIfy(int[] arr,int index,int heapSize){//左孩子下标int left = index*2+1;//左孩子下标还没有越界,证明还有孩子while(left<heapSize){//左右孩子PKint largest = left +1 <heapSize && arr[left+1]>arr[left]?left+1:   //如果右孩子的下标没有越界 且 右孩子比左孩子大left;   //反之,右孩子越界或左孩子比较大则都选左孩子//父节点和较大的孩子节点PKif (arr[largest] > arr[index]){  //孩子节点比较大//孩子节点与父节点交换swap(arr,largest,index);index = largest;    //此时的父节点处在孩子节点的位置left = index *2 +1;   //此时的父节点的左孩子位置//继续循环换位置}else {   //孩子节点没有比父节点大,大根堆形成break;}}}
堆中某个位置的数值发生改变
  1. 变大:往上进行heapInsert
  2. 变小:往下惊醒heapIfy

堆排序

  1. 调整成大根堆,剔除最大值(根节点),将最后一个位置上的数放到根节点上,heapSize–
  2. 继续调整,剔除,更新位置,heapSize
  3. 直到排序完成

代码实现:

     /*** 堆排序代码实现* @param arr*/public static void heapSort(int[] arr){//arr为空或arr只有一个或零个数if(arr==null || arr.length<2){return;}//初始大根堆for (int i = 0;i<arr.length;i++){  //O(N)heapInsert(arr,i);   //O(log N)}int heapSize = arr.length;  //初始大根堆长度swap(arr,0,-heapSize);   //0位置上堆中最后的位置做交换//当堆的长度不为0时,需要不断拿走根节点,再重新调整while (heapSize > 0){    //O(N)heapIfy(arr,0,heapSize);    //O(log N)swap(arr,0,--heapSize);}}

优化

在这里插入图片描述

在这里插入图片描述

完全二叉树的叶子节点:

  1. 如果是偶数个节点,叶子节点等于总节点除以2, 即 N % 2==0, n = N/2
  2. 如果是奇数个节点,叶子节点等于==(总节点+1)除以2==, 即 N % 2 == 1, n = (N+1)/2

时间复杂度:假设数组中有N个数,叶子节点为N/2个叶子节点

  1. 最底层的叶子节点的时间复杂度即为:(N/2)*1(1为只进行一次操作,因为叶子节点没有子节点,只遍历)
  2. 倒数第二层的节点的时间复杂度:(N/4)*2(2为 遍历+往下移动一层)
  3. 倒数第三层的节点的时间复杂度:(N/8)*3(3为 遍历+往下移动2层)
  4. 以此类推

T ( N ) = N / 2 ∗ 1 + N / 4 ∗ 2 + N / 8 ∗ 3 + . . . + 1 ∗ l o g 2 N T(N)=N/2*1+N/4*2+N/8*3+...+1*log2 N T(N)=N/21+N/42+N/83+...+1log2N

错位相减2T(N)-T(N)==T(N) 结果为O(N)

代码实现:

        //更快的初始化堆的方法    时间复杂度O(N)for (int i = arr.length-1;i>=0;i--){heapIfy(arr,i, arr.length);}

堆练习

堆排序扩展题目
已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。

题解:

每一个元素移动的距离都不超过K:意味着,在数组的 0~K 的范围内的最小值即为整个数组的最小值,K+1位置以后的数也全都不可能移动到 0 位置上。

所以,只需要 使用一个固定长度为 K+1的滑动窗口或双指针,不断的选出该范围内的最小值,然后不断地推后该滑动窗口。

Java中现成的堆结构:优先级队列

PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();

默认小根堆,想要大根堆则传入比较器指定比较挥着

底层是数组:

扩容机制???

默认堆结构,只支持用户给出一个数,和系统弹出最值并移除(黑盒)

比较器

public static class myCompare implements Comparator<Integer> {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}
}

桶排序

之前所有的排序都是只和两个数之间的比较有关系。(基于比较的排序)

不基于比较的排序(根据数据状况定制):

例子:员工年龄排序,返回0-200

解题思路:申请一个长度为200的数组,下标 i 认为是年龄,i 位置的值为年龄为 i 的人数。

时间复杂度:O(N)

不基于比较的排序都是根据数据状况做的排序,应用范围比基于比较的排序小。

基数排序

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/229703.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

知识工作者,需要填报工时么? | IDCF

作者&#xff1a;冬哥 来源&#xff1a;DevOps 引 子 “知识工作者&#xff0c;需要填报工时么&#xff1f;”忘记是因为什么&#xff0c;突然想到这个话题。似乎是没什么值得讨论的话题&#xff0c;我们的观点也是旗帜鲜明地认为没有必要&#xff0c;但实际现实中填报工时似…

selenium+python

selenium 八大查找元素 from selenium import webdriver from selenium.webdriver.common.by import By# 创建一个 WebDriver 实例 driver webdriver.Chrome()# 打开网页 driver.get("https://www.baidu.com/")# 使用 find_element 方法查找元素 element driver.…

使用elasticsearch-head插件修改elasticsearch数据

1、先使用elasticsearch-head插件基本查询功能找到要修改的数据&#xff0c;看看是否存在 2、切换到elasticsearch-head复合查询界面&#xff0c;输入数据修改地址&#xff1a; http://es的ip地址:端口号/索引名称/文档类型&#xff08;没特殊设置过就是_doc&#xff09;/文档…

C# API 文档自动生成器

文章目录 前言SandcastleDocFX 前言 最近要和别人交际&#xff0c;就要给API文档&#xff0c;但是感觉API文件手动写有点麻烦&#xff0c;想着怎么弄一个自动API文档生成 Sandcastle 折腾了两小时&#xff0c;好像不太好用 微软开源全新的文档生成工具DocFX DocFX 既然不好…

使用Moment.js中获取上周的开始日期和结束日期(可自定义)

前言 有时候需求是这样的&#xff0c;想要获取上周的开始日期和结束日期&#xff0c;或者前几周的时间范围 比如今天是2023.11.28号&#xff0c;我想获取上周的周一到周日&#xff0c;也就是&#xff0c;上周的开始日期: 2023-11-20&#xff0c;上周的结束日期: 2023-11-26 1.…

c++day1

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {string str;cout << "请输入一个含有大小写字母&#xff0c;空格&am…

wsl 命令详解

WSL 简介 WSL全称 Windows Subsystem for Linux &#xff0c;是微软开发的一个运行在Windows上的兼容层&#xff0c;它允许开发人员和用户直接在Windows上运行原生Linux二进制文件&#xff0c;而无需配置或修改系统。 WSL命令是用于管理和操作WSL子系统的工具。 常用WSL命令…

Linux 启动过程

linux启动步骤&#xff1a; <1>加电 <2>加载bios设置 <3>加载grup <4>加载内核系统到内存中 <5>加载配置文件 <6>加载内核模块 <7>完成相应的初始化工作和启动相应的服务 <8>启动系统进程 <9>出现登录界面 &l…

快捷键被占用了,这能忍吗?赶紧使用 OpenArk 找出元凶并干掉它!!!

文章目录 一、 问题&#xff1a;快捷键被占用了导致影响工作效率二、OpenArk 2.1 OpenArk简介 功能发布官方链接 2.2 下载OpenArk2.3 运行OpenArk2.4 被占用的热键元凶到底是谁&#xff1f; 三、总结 一、 问题&#xff1a;快捷键被占用了导致影响工作效率 你是否遇到过&#x…

王者荣耀游戏制作

1.创建所需要的包 2.创建怪物类 bear package beast;import wangzherogyao.GameFrame;public class Bear extends Beast {public Bear(int x, int y, GameFrame gameFrame) {super(x, y, gameFrame);setImg("img/bear.jpg");width 85;height 112;setDis(65);}} b…

Java核心知识点整理大全22-笔记

目录 19.1.14. CAP 一致性&#xff08;C&#xff09;&#xff1a; 可用性&#xff08;A&#xff09;&#xff1a; 分区容忍性&#xff08;P&#xff09;&#xff1a; 20. 一致性算法 20.1.1. Paxos Paxos 三种角色&#xff1a;Proposer&#xff0c;Acceptor&#xff0c;L…

好用的chatgpt工具用过这个比较快

chatgpthttps://www.askchat.ai?r237422 chatGPT能做什么 1. 对话和聊天&#xff1a;我可以与您进行对话和聊天&#xff0c;回答您的问题、提供信息和建议。 2. 问题回答&#xff1a;无论是关于事实、历史、科学、文化、地理还是其他领域的问题&#xff0c;我都可以尽力回答…