算法02 七大排序之:直接选择排序和堆排序
时间:2022-05-04
本文章向大家介绍算法02 七大排序之:直接选择排序和堆排序,主要内容包括1、直接选择排序及算法实现、1-2、代码、2、堆排序及算法实现、2-2、代码、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
上一篇总结了交换排序的冒泡排序和快速排序。这一篇要总结的是选择排序,选择排序分为直接选择排序和堆排序,主要从以下几点进行总结。
1、直接选择排序及算法实现
2、堆排序及算法实现
1、直接选择排序及算法实现
直接选择排序(Straight Select Sort) 是一种简单的排序方法,它的基本思想是:通过length-1 趟元素之间的比较,从length-i+1个元素中选出最小的元素,并和第i个元素交换位置。直接选择排序的最坏时间复杂度为O(n2),平均时间复杂度为O(n2)
下图展示了直接选择排序的过程。
1-1、示意图
1-2、代码
SelectionSort.java
public class SelectionSort {
public static void main(String[] args) {
int[] list = {9, 1, 2, 5, 7, 4, 8, 6, 3, 5};
System.out.println("************直接选择排序************");
System.out.println("排序前:");
display(list);
System.out.println("");
System.out.println("排序后:");
selectionSort(list);
display(list);
}
/**
* 直接选择排序算法
*/
public static void selectionSort(int[] list) {
// 要遍历的次数(length-1次)
for (int i = 0; i < list.length - 1; i++) {
// 将当前下标定义为最小值下标
int min = i;
// 遍历min后面的数据
for (int j = i + 1; j <= list.length - 1; j++) {
// 如果有小于当前最小值的元素,将它的下标赋值给min
if (list[j] < list[min]) {
min = j;
}
}
// 如果min不等于i,说明找到真正的最小值
if (min != i) {
swap(list, min, i);
}
}
}
/**
* 交换数组中两个位置的元素
*/
public static void swap(int[] list, int min, int i) {
int temp = list[min];
list[min] = list[i];
list[i] = temp;
}
/**
* 遍历打印
*/
public static void display(int[] list) {
System.out.println("********展示开始********");
if (list != null && list.length > 0) {
for (int num :
list) {
System.out.print(num + " ");
}
System.out.println("");
}
System.out.println("********展示结束********");
}
}
测试结果:
2、堆排序及算法实现
堆排序(Heap Sort) 利用堆(一般为大根堆)进行排序的方法。它的基本思想是:将待排序的元素构造成一个大根堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是将它与数组的末尾元素进行交换,此时末尾元素就是最大值),然后将剩余的length-1 个元素重新构造成一个大根堆,这样就会得到length个元素中的次大值。如此反复执行,便能得到一个有序的序列。
堆是具有下列性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,称为大根堆;每个节点的值都小于或等于其左右孩子节点的值,称为小根堆。
堆排序的最坏时间复杂度为O(n*log2n),平均时间复杂度为O(n*log2n)
2-1、示意图
图一:
图二:
图三:
图四:
图五:
图六:
2-2、代码
HeapSort.java
public class HeapSort {
public static void main(String[] args) {
int[] list = {1, 3, 4, 5, 2, 6, 9, 7, 8, 0};
System.out.println("************堆排序************");
System.out.println("排序前:");
display(list);
System.out.println("");
System.out.println("排序后:");
heapSort(list);
display(list);
}
/**
* 堆排序算法
*/
public static void heapSort(int[] list) {
// 将无序堆构造成一个大根堆,大根堆有length/2个父节点
for (int i = list.length / 2 - 1; i >= 0; i--) {
headAdjust(list, i, list.length);
}
// 逐步将每个最大值的根节点与末尾元素交换,并且再调整其为大根堆
for (int i = list.length - 1; i > 0; i--) {
// 将堆顶节点和当前未经排序的子序列的最后一个元素交换位置
swap(list, 0, i);
headAdjust(list, 0, i);
}
}
/**
* 构造大根堆
*/
public static void headAdjust(int[] list, int parent, int length) {
// 保存当前父节点
int temp = list[parent];
// 得到左孩子节点
int leftChild = 2 * parent + 1;
while (leftChild < length) {
// 如果parent有右孩子,则要判断左孩子是否小于右孩子
if (leftChild + 1 < length && list[leftChild] < list[leftChild + 1]) {
leftChild++;
}
// 父亲节点大于子节点,就不用做交换
if (temp >= list[leftChild]) {
break;
}
// 将较大子节点的值赋给父亲节点
list[parent] = list[leftChild];
// 然后将子节点做为父亲节点
parent = leftChild;
// 找到该父亲节点较小的左孩子节点
leftChild = 2 * parent + 1;
}
// 最后将temp值赋给较大的子节点,以形成两值交换
list[parent] = temp;
}
/**
* 交换数组中两个位置的元素
*/
public static void swap(int[] list, int top, int last) {
int temp = list[top];
list[top] = list[last];
list[last] = temp;
}
/**
* 遍历打印
*/
public static void display(int[] list) {
System.out.println("********展示开始********");
if (list != null && list.length > 0) {
for (int num :
list) {
System.out.print(num + " ");
}
System.out.println("");
}
System.out.println("********展示结束********");
}
}
测试结果:
- 关于执行计划中的%CPU的含义 (r7笔记第25天)
- Java设计模式-享元模式
- 简单易学的机器学习算法——线性可分支持向量机
- 基于gensim的Doc2Vec简析,以及用python 实现简要代码
- 关于db link权限分配的苦旅(一) (r7笔记第42天)
- Java设计模式-责任链模式
- Java设计模式-策略模式
- CPU 100%负载的性能优化分析(r7笔记第40天)
- Sklearn-train_test_split随机划分训练集和测试集
- 使用shell来定制dbms_sqltune(r7笔记第39天)
- 简单易学的机器学习算法——分类回归树CART
- Java设计模式-状态模式
- DBA和开发同事的一些代沟(四) (r7笔记第36天)
- python获取文件所在目录和文件名,以及检索当前文件名的方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- LeetCode88|两数之和IV-输入BST
- LeetCode98|判定字符是否唯一
- LeetCode97|合并两个有序链表
- LeetCode99|数组中出现次数超过一半的数字
- redis源码之hash结构的实现
- redis源码之set结构
- redis源码之zset结构的实现
- Elasticsearch: range 数据类型及基于range的聚合 (7.4发行版新功能)
- 漫画:如何在数组中找到和为 “特定值” 的三个数?
- 除了MySQL,大牛DBA还会啥?
- 用 Docker swarm 快速部署分布式图数据库 Nebula Graph 集群
- Labelhub 基于腾讯云 Serverless 技术为人工智能企业提供数据与模型解决方案
- 手把手教你使用 Prometheus 监控 JVM
- 基于云开发 CloudBase 搭建在线视频会议应用
- 手搓一个分布式大气监测系统(六)云端能力更新、说明及源码放出