Skip to content

Commit f0f0fca

Browse files
committed
添加:堆排序理论介绍
1 parent 9c4db53 commit f0f0fca

File tree

12 files changed

+134
-1
lines changed

12 files changed

+134
-1
lines changed

Data Structures and Algorithms/sort/README.md

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@
3535
- <a href="#selectionsort">`选择排序(Selection Sort`</a>
3636
- <a href="#insertionsort">`插入排序(Insertion Sort`</a>
3737
- <a href="#shellsort">`希尔排序(Shell Sort`</a>
38+
- <a href="#heapsort">`堆排序(heap Sort`</a>
39+
- <a href="#mergesort">`归并排序(merge Sort`</a>
3840
- <a href="#fastsort">`快速排序(Fast Sort`</a>
3941

4042

4143
## 常见排序算法复杂度
4244

43-
![常用排序算法](images/sort_algorithms_2.png)
45+
![常用排序算法1](images/sort_algorithms_1.png)
46+
47+
![常用排序算法2](images/sort_algorithms_2.png)
4448

4549
- [8大排序算法稳定性分析](https://www.cnblogs.com/codingmylife/archive/2012/10/21/2732980.html)
4650

@@ -720,6 +724,135 @@ print("InsertionnSort: ", array)
720724
- [理解希尔排序的排序过程](https://blog.csdn.net/weixin_37818081/article/details/79202115)
721725
- [图解排序算法(二)之希尔排序](https://www.cnblogs.com/chengxiao/p/6104371.html)
722726

727+
728+
729+
<a id="heapsort"/>
730+
731+
## 堆排序(Heap Sort)
732+
733+
**基本思想**
734+
735+
[堆排序(heap sort)](https://en.wikipedia.org/wiki/Heapsort):将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
736+
737+
注:堆排序是一种选择排序,指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
738+
739+
在介绍堆排序之前,先了解一下什么是**堆(heap)**
740+
741+
****
742+
743+
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
744+
745+
![堆结构](images/heap.png)
746+
747+
同时,我们对堆的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子:
748+
749+
![](images/heap2.png)
750+
751+
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:
752+
753+
**大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] **
754+
755+
**小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] **
756+
757+
ok,了解了这些定义。接下来,我们来看看堆排序的基本思想及基本步骤:
758+
759+
**步骤**
760+
761+
- 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
762+
- 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n]
763+
- 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
764+
765+
**动图演示**
766+
767+
![堆排序](images/heap_sort.gif)
768+
769+
看到这里,你可能还是晕乎乎的,下面看个讲解示例:
770+
771+
**步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。**
772+
773+
a.假设给定无序序列结构如下
774+
775+
![img](images/heap_p1.png)
776+
777+
b.此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点 arr.length/2-1=5/2-1=1,也就是下面的6结点),从左至右,从下至上进行调整。
778+
779+
![img](images/heap_p2.png)
780+
781+
c.找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换。
782+
783+
![img](images/heap_p3.png)
784+
785+
d.这时交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。
786+
787+
![img](images/heap_p4.png)
788+
789+
此时,我们就将一个无需序列构造成了一个大顶堆。
790+
791+
**步骤二 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。**
792+
793+
a.将堆顶元素9和末尾元素4进行交换
794+
795+
![img](images/heap_p5.png)
796+
797+
b.重新调整结构,使其继续满足堆定义
798+
799+
![img](images/heap_p6.png)
800+
801+
c.再将堆顶元素8与末尾元素5进行交换,得到第二大元素8.
802+
803+
![img](images/heap_p7.png)
804+
805+
后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序
806+
807+
![img](images/heap_p8.png)
808+
809+
再简单总结下堆排序的基本思路:
810+
811+
**a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;**
812+
813+
**b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;**
814+
815+
**c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。**
816+
817+
**复杂度分析**
818+
819+
堆排序整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。
820+
821+
时间复杂度:
822+
823+
- 最差:O(nlogn)
824+
- 平均:O(nlogn)
825+
- 最优:O(nlogn)
826+
827+
空间复杂度:O(n)
828+
829+
稳定性:不稳定
830+
831+
**代码实现**
832+
833+
- [ ] TODO
834+
835+
836+
837+
参考:
838+
839+
- [图解排序算法(三)之堆排序](https://www.cnblogs.com/chengxiao/p/6129630.html)
840+
- [heap-sort](https://www.geeksforgeeks.org/heap-sort/)
841+
842+
843+
844+
<a id="mergesort"/>
845+
846+
## 归并排序(Merge Sort)
847+
848+
**基本思想**
849+
850+
[归并排序(merge sort)](https://en.wikipedia.org/wiki/Merge_sort)
851+
852+
**步骤**
853+
854+
- [ ] TODO
855+
723856
<a id="fastsort"/>
724857

725858
## 快速排序(Quick Sort)
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)