|
35 | 35 | - <a href="#selectionsort">`选择排序(Selection Sort`</a>
|
36 | 36 | - <a href="#insertionsort">`插入排序(Insertion Sort`</a>
|
37 | 37 | - <a href="#shellsort">`希尔排序(Shell Sort`</a>
|
| 38 | +- <a href="#heapsort">`堆排序(heap Sort`</a> |
| 39 | +- <a href="#mergesort">`归并排序(merge Sort`</a> |
38 | 40 | - <a href="#fastsort">`快速排序(Fast Sort`</a>
|
39 | 41 |
|
40 | 42 |
|
41 | 43 | ## 常见排序算法复杂度
|
42 | 44 |
|
43 |
| - |
| 45 | + |
| 46 | + |
| 47 | + |
44 | 48 |
|
45 | 49 | - [8大排序算法稳定性分析](https://www.cnblogs.com/codingmylife/archive/2012/10/21/2732980.html)
|
46 | 50 |
|
@@ -720,6 +724,135 @@ print("InsertionnSort: ", array)
|
720 | 724 | - [理解希尔排序的排序过程](https://blog.csdn.net/weixin_37818081/article/details/79202115)
|
721 | 725 | - [图解排序算法(二)之希尔排序](https://www.cnblogs.com/chengxiao/p/6104371.html)
|
722 | 726 |
|
| 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 | + |
| 746 | + |
| 747 | +同时,我们对堆的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子: |
| 748 | + |
| 749 | + |
| 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 | + |
| 768 | + |
| 769 | +看到这里,你可能还是晕乎乎的,下面看个讲解示例: |
| 770 | + |
| 771 | +**步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。** |
| 772 | + |
| 773 | +a.假设给定无序序列结构如下 |
| 774 | + |
| 775 | + |
| 776 | + |
| 777 | +b.此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点 arr.length/2-1=5/2-1=1,也就是下面的6结点),从左至右,从下至上进行调整。 |
| 778 | + |
| 779 | + |
| 780 | + |
| 781 | +c.找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换。 |
| 782 | + |
| 783 | + |
| 784 | + |
| 785 | +d.这时交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。 |
| 786 | + |
| 787 | + |
| 788 | + |
| 789 | +此时,我们就将一个无需序列构造成了一个大顶堆。 |
| 790 | + |
| 791 | +**步骤二 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。** |
| 792 | + |
| 793 | +a.将堆顶元素9和末尾元素4进行交换 |
| 794 | + |
| 795 | + |
| 796 | + |
| 797 | +b.重新调整结构,使其继续满足堆定义 |
| 798 | + |
| 799 | + |
| 800 | + |
| 801 | +c.再将堆顶元素8与末尾元素5进行交换,得到第二大元素8. |
| 802 | + |
| 803 | + |
| 804 | + |
| 805 | +后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序 |
| 806 | + |
| 807 | + |
| 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 | + |
723 | 856 | <a id="fastsort"/>
|
724 | 857 |
|
725 | 858 | ## 快速排序(Quick Sort)
|
|
0 commit comments