auto commit

This commit is contained in:
CyC2018
2019-11-02 12:07:41 +08:00
parent 182e1440a4
commit bb6e0df82d
784 changed files with 7545 additions and 2827 deletions

View File

@ -1,32 +1,3 @@
<!-- GFM-TOC -->
* [约定](#约定)
* [选择排序](#选择排序)
* [冒泡排序](#冒泡排序)
* [插入排序](#插入排序)
* [希尔排序](#希尔排序)
* [归并排序](#归并排序)
* [1. 归并方法](#1-归并方法)
* [2. 自顶向下归并排序](#2-自顶向下归并排序)
* [3. 自底向上归并排序](#3-自底向上归并排序)
* [快速排序](#快速排序)
* [1. 基本算法](#1-基本算法)
* [2. 切分](#2-切分)
* [3. 性能分析](#3-性能分析)
* [4. 算法改进](#4-算法改进)
* [5. 基于切分的快速选择算法](#5-基于切分的快速选择算法)
* [堆排序](#堆排序)
* [1. ](#1-)
* [2. 上浮和下沉](#2-上浮和下沉)
* [3. 插入元素](#3-插入元素)
* [4. 删除最大元素](#4-删除最大元素)
* [5. 堆排序](#5-堆排序)
* [6. 分析](#6-分析)
* [小结](#小结)
* [1. 排序算法的比较](#1-排序算法的比较)
* [2. Java 的排序算法实现](#2-java-的排序算法实现)
<!-- GFM-TOC -->
# 约定
待排序的元素需要实现 Java Comparable 接口该接口有 compareTo() 方法可以用它来判断两个元素的大小关系
@ -58,7 +29,7 @@ public abstract class Sort<T extends Comparable<T>> {
选择排序需要 \~N<sup>2</sup>/2 次比较和 \~N 次交换它的运行时间与输入无关这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bc6be2d0-ed5e-4def-89e5-3ada9afa811a.gif" width="230px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bc6be2d0-ed5e-4def-89e5-3ada9afa811a.gif" width="230px">
```java
public class Selection<T extends Comparable<T>> extends Sort<T> {
@ -85,7 +56,7 @@ public class Selection<T extends Comparable<T>> extends Sort<T> {
在一轮循环中如果没有发生交换那么说明数组已经是有序的此时可以直接退出
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0f8d178b-52d8-491b-9dfd-41e05a952578.gif" width="200px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0f8d178b-52d8-491b-9dfd-41e05a952578.gif" width="200px">
```java
public class Bubble<T extends Comparable<T>> extends Sort<T> {
@ -119,7 +90,7 @@ public class Bubble<T extends Comparable<T>> extends Sort<T> {
- 最坏的情况下需要 \~N<sup>2</sup>/2 比较以及 \~N<sup>2</sup>/2 次交换最坏的情况是数组是倒序的
- 最好的情况下需要 N-1 次比较和 0 次交换最好的情况就是数组已经有序了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/35253fa4-f60a-4e3b-aaec-8fc835aabdac.gif" width="200px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/35253fa4-f60a-4e3b-aaec-8fc835aabdac.gif" width="200px">
```java
public class Insertion<T extends Comparable<T>> extends Sort<T> {
@ -142,7 +113,7 @@ public class Insertion<T extends Comparable<T>> extends Sort<T> {
希尔排序使用插入排序对间隔 h 的序列进行排序通过不断减小 h最后令 h=1就可以使得整个数组是有序的
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7818c574-97a8-48db-8e62-8bfb030b02ba.png" width="450px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7818c574-97a8-48db-8e62-8bfb030b02ba.png" width="450px">
```java
public class Shell<T extends Comparable<T>> extends Sort<T> {
@ -176,7 +147,7 @@ public class Shell<T extends Comparable<T>> extends Sort<T> {
归并排序的思想是将数组分成两部分分别进行排序然后归并起来
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ec840967-d127-4da3-b6bb-186996c56746.png" width="300px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ec840967-d127-4da3-b6bb-186996c56746.png" width="300px">
## 1. 归并方法
@ -272,7 +243,7 @@ public class Down2UpMergeSort<T extends Comparable<T>> extends MergeSort<T> {
- 归并排序将数组分为两个子数组分别排序并将有序的子数组归并使得整个数组排序
- 快速排序通过一个切分元素将数组分为两个子数组左子数组小于等于切分元素右子数组大于等于切分元素将这两个子数组排序也就将整个数组排序了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6234eb3d-ccf2-4987-a724-235aef6957b1.png" width="280px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6234eb3d-ccf2-4987-a724-235aef6957b1.png" width="280px">
```java
public class QuickSort<T extends Comparable<T>> extends Sort<T> {
@ -303,7 +274,7 @@ public class QuickSort<T extends Comparable<T>> extends Sort<T> {
a[l] 作为切分元素然后从数组的左端向右扫描直到找到第一个大于等于它的元素再从数组的右端向左扫描找到第一个小于它的元素交换这两个元素不断进行这个过程就可以保证左指针 i 的左侧元素都不大于切分元素右指针 j 的右侧元素都不小于切分元素当两个指针相遇时将切分元素 a[l] a[j] 交换位置
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c4859290-e27d-4f12-becf-e2a5c1f3a275.gif" width="320px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c4859290-e27d-4f12-becf-e2a5c1f3a275.gif" width="320px">
```java
private int partition(T[] nums, int l, int h) {
@ -407,7 +378,7 @@ public T select(T[] nums, int k) {
堆可以用数组来表示这是因为堆是完全二叉树而完全二叉树很容易就存储在数组中位置 k 的节点的父节点位置为 k/2而它的两个子节点的位置分别为 2k 2k+1这里不使用数组索引为 0 的位置是为了更清晰地描述节点的位置关系
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f48883c8-9d8a-494e-99a4-317d8ddb8552.png" width="170px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f48883c8-9d8a-494e-99a4-317d8ddb8552.png" width="170px">
```java
public class Heap<T extends Comparable<T>> {
@ -443,7 +414,7 @@ public class Heap<T extends Comparable<T>> {
在堆中当一个节点比父节点大那么需要交换这个两个节点交换后还可能比它新的父节点大因此需要不断地进行比较和交换操作把这种操作称为上浮
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/99d5e84e-fc2a-49a3-8259-8de274617756.gif" width="270px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/99d5e84e-fc2a-49a3-8259-8de274617756.gif" width="270px">
```java
private void swim(int k) {
@ -456,7 +427,7 @@ private void swim(int k) {
类似地当一个节点比子节点来得小也需要不断地向下进行比较和交换操作把这种操作称为下沉一个节点如果有两个子节点应当与两个子节点中最大那个节点进行交换
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4bf5e3fb-a285-4138-b3b6-780956eb1df1.gif" width="270px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4bf5e3fb-a285-4138-b3b6-780956eb1df1.gif" width="270px">
```java
private void sink(int k) {
@ -505,13 +476,13 @@ public T delMax() {
无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作一个更高效的方法是从右至左进行下沉操作如果一个节点的两个节点都已经是堆有序那么进行下沉操作可以使得这个节点为根节点的堆有序叶子节点不需要进行下沉操作可以忽略叶子节点的元素因此只需要遍历一半的元素即可
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c2ca8dd2-8d00-4a3e-bece-db7849ac9cfd.gif" width="210px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c2ca8dd2-8d00-4a3e-bece-db7849ac9cfd.gif" width="210px">
#### 5.2 交换堆顶元素与最后一个元素
交换之后需要进行下沉操作维持堆的有序状态
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d156bcda-ac8d-4324-95e0-0c8df41567c9.gif" width="250px"> </div><br>
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d156bcda-ac8d-4324-95e0-0c8df41567c9.gif" width="250px">
```java
public class HeapSort<T extends Comparable<T>> extends Sort<T> {
@ -580,10 +551,3 @@ public class HeapSort<T extends Comparable<T>> extends Sort<T> {
## 2. Java 的排序算法实现
Java 主要排序方法为 java.util.Arrays.sort()对于原始数据类型使用三向切分的快速排序对于引用类型使用归并排序
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-1.png"></img></div>