mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2025-08-16 19:01:45 +00:00
代码重构 【Github Actions】
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
### **堆排序**
|
||||
|
||||
> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
|
||||
> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
|
||||
>
|
||||
> 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。
|
||||
>刷题网站
|
||||
> 另外希望手机阅读的同学可以来我的 <u>[**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
|
||||
> 刷题网站
|
||||
> 另外希望手机阅读的同学可以来我的 <u>[**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
|
||||
|
||||
说堆排序之前,我们先简单了解一些什么是堆?堆这种数据结构应用场景非常多,所以我们需要熟练掌握呀!
|
||||
|
||||
@@ -46,15 +46,13 @@
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
我们来看一下为什么我们可以用数组来存储堆呢?
|
||||
|
||||
我们首先看根节点,也就是值为 1 的节点,它在数组中的下标为 1 ,它的左子节点,也就是值为 4 的节点,此时索引为 2,右子节点也就是值为 2 的节点,它的索引为 3。
|
||||
|
||||
我们发现其中的关系了吗?
|
||||
|
||||
数组中,某节点(非叶子节点)的下标为 i , 那么其**左子节点下标为 2*i** (这里可以直接通过相乘得到左孩子,如果从0 开始存,需要 2*i+1 才行), 右子节点为 2*i+1**,**其父节点为 i/2 。既然我们完全可以根据索引找到某节点的 **左子节点** 和 **右子节点**,那么我们用数组存储是完全没有问题的。
|
||||
数组中,某节点(非叶子节点)的下标为 i , 那么其**左子节点下标为 2\*i** (这里可以直接通过相乘得到左孩子,如果从 0 开始存,需要 2*i+1 才行), 右子节点为 2*i+1**,**其父节点为 i/2 。既然我们完全可以根据索引找到某节点的 **左子节点** 和 **右子节点**,那么我们用数组存储是完全没有问题的。
|
||||
|
||||
好啦,我们知道了什么是堆和如何用数组存储堆,那我们如何完成堆排序呢?
|
||||
|
||||
@@ -77,7 +75,7 @@
|
||||
|
||||

|
||||
|
||||
假设让我们插入新的元素 1 (绿色节点),我们发现此时 1 小于其父节点 的值 7 ,并不遵守小顶堆的规则,那我们则需要移动元素 1 。让 1 与 7 交换,(如果新插入元素大于父节点的值,则说明插入新节点后仍满足小顶堆规则,无需交换)。
|
||||
假设让我们插入新的元素 1 (绿色节点),我们发现此时 1 小于其父节点 的值 7 ,并不遵守小顶堆的规则,那我们则需要移动元素 1 。让 1 与 7 交换,(如果新插入元素大于父节点的值,则说明插入新节点后仍满足小顶堆规则,无需交换)。
|
||||
|
||||
之前我们说过,我们可以用数组保存堆,并且可以通过 i/2 得到其父节点的值,那么此时我们就明白怎么做啦。
|
||||
|
||||
@@ -139,7 +137,7 @@ def swim(nums: int, index: int):
|
||||
|
||||
那我们怎么判断节点找到属于它的位置了呢?主要有两个情况
|
||||
|
||||
- 待下沉元素小于(大于)两个子节点,此时符合堆的规则,无序下沉,例如上图中的 6
|
||||
- 待下沉元素小于(大于)两个子节点,此时符合堆的规则,无序下沉,例如上图中的 6
|
||||
- 下沉为叶子节点,此时没有子节点,例如 7 下沉到最后变成了叶子节点。
|
||||
|
||||
我们将上面的操作称之为下沉操作。
|
||||
@@ -171,7 +169,7 @@ public void sink (int[] nums, int index,int len) {
|
||||
swap(nums,index,j);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//继续下沉
|
||||
index = j;
|
||||
}
|
||||
@@ -202,7 +200,7 @@ def sink(nums: list, index: int, len: int):
|
||||
|
||||

|
||||
|
||||
假设我们想要去除堆顶的 11 ,那我们则需要将其与堆的最后一个节点交换也就是 2 ,2然后再执行下沉操作,执行完毕后仍能满足堆的要求,见下图
|
||||
假设我们想要去除堆顶的 11 ,那我们则需要将其与堆的最后一个节点交换也就是 2 ,2 然后再执行下沉操作,执行完毕后仍能满足堆的要求,见下图
|
||||
|
||||

|
||||
|
||||
@@ -229,7 +227,7 @@ class Solution {
|
||||
|
||||
for (int i = 0; i < nums.length; ++i) {
|
||||
a[i+1] = nums[i];
|
||||
}
|
||||
}
|
||||
//下沉建堆
|
||||
for (int i = len/2; i >= 1; --i) {
|
||||
sink(a,i,len);
|
||||
@@ -267,7 +265,7 @@ class Solution {
|
||||
nums[i] = nums[j];
|
||||
nums[j] = temp;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@@ -287,7 +285,7 @@ def sortArray(nums: list)->list:
|
||||
swap(a, 1, k)
|
||||
k -= 1
|
||||
sink(a, 1, k)
|
||||
|
||||
|
||||
for i in range(1, leng + 1):
|
||||
nums[i - 1] = a[i]
|
||||
return nums
|
||||
@@ -319,7 +317,7 @@ def sink(nums: list, k: int, end: int):
|
||||
|
||||
**堆排序空间复杂度分析**
|
||||
|
||||
这里需要注意,我们上面的描述过程中,为了更直观的描述,空出数组的第一位,这样我们就可以通过 i * 2 和 i * 2+1 来求得左孩子节点和右孩子节点 。我们也可以根据 i * 2 + 1 和 i * 2 + 2 来获取孩子节点,这样则不需要临时数组来处理原数组,将所有元素后移一位,所以堆排序的空间复杂度为 O(1),是原地排序算法。
|
||||
这里需要注意,我们上面的描述过程中,为了更直观的描述,空出数组的第一位,这样我们就可以通过 i _ 2 和 i _ 2+1 来求得左孩子节点和右孩子节点 。我们也可以根据 i _ 2 + 1 和 i _ 2 + 2 来获取孩子节点,这样则不需要临时数组来处理原数组,将所有元素后移一位,所以堆排序的空间复杂度为 O(1),是原地排序算法。
|
||||
|
||||
**堆排序稳定性分析**
|
||||
|
||||
@@ -334,4 +332,3 @@ def sink(nums: list, k: int, end: int):
|
||||
所以上面两条也就说明了在实际开发中,堆排序的性能不如快速排序性能好。
|
||||
|
||||
好啦,今天的内容就到这里啦,咱们下期见。
|
||||
|
||||
|
Reference in New Issue
Block a user