chapter_sorting/heap_sort/ #517
Replies: 10 comments 17 replies
-
if (l < n && nums[l] > nums[ma])
ma = l;
if (r < n && nums[r] > nums[ma])
ma = r; 这里代码和堆那节siftDowm代码有点不一样,这样不能判断三个里面谁最大吧 |
Beta Was this translation helpful? Give feedback.
-
有时候看指针看着头有点晕,心里知道指针指向的是元素的索引,但自己去想总弄混到元素上 |
Beta Was this translation helpful? Give feedback.
-
我觉得图片里的那个例子交换元素后进行大根堆调整的过程体现不够明显 |
Beta Was this translation helpful? Give feedback.
-
// 建堆操作:堆化除叶节点以外的其他所有节点
for (int i = nums.length / 2 - 1; i >= 0; i--) {
siftDown(nums, nums.length, i);
} 获取最后一个非叶子节点的索引,友情提示 |
Beta Was this translation helpful? Give feedback.
-
public static void heapSort(int[] nums){
//初始化堆
for(int i= nums.length/2-1;i>=0;i--){//((nums.length-1)-1)/2
siftDown(nums, nums.length, i);
}
for(int i= nums.length;i>0;i--){//有效长度(迭代有效长度)
swap(nums,0,i-1);//首和有效区间的尾交换,即0和有效长度-1
siftDown(nums,i-1,0);//向下堆化,此时有效长度已经-1了,因为已经“出去一个”
}
} 直接从nums.length-1开始逆序遍历有点不好理解,虽然结果对了 |
Beta Was this translation helpful? Give feedback.
-
作者好, |
Beta Was this translation helpful? Give feedback.
-
堆排序(从大到小,C语言版本) void getLeftChild(int i, int *lc_idx) { *lc_idx = 2 * i + 1; }
void getRightChild(int i, int *rc_idx) { *rc_idx = 2 * i + 2; }
void heaptifyDown(float *arr, int size, int idx) { // 比较当前节点与其左右子节点的大小。选择最小的子节点,如果当前节点大于这个子节点,则交换它们,并继续向下调整。
int cur = idx;
while (true) {
int lc, rc, minidx = cur; getLeftChild(cur, &lc); getRightChild(cur, &rc);
if (lc < size && arr[lc] < arr[minidx]) { minidx = lc; } // 找到当前节点和左子节点中的最小值
if (rc < size && arr[rc] < arr[minidx]) { minidx = rc; } // 找到当前节点和右子节点中的最小值
if (minidx == cur) break; // 如果当前节点是最小值,退出循环
float tmp = arr[cur]; arr[cur] = arr[minidx]; arr[minidx] = tmp; cur = minidx; // 交换当前节点和最小值节点, 更新 cur 为新的索引
}
}
void freeHeap(float **arr) { if (*arr) { free(*arr); *arr = NULL; } }
void buildHeap(float *arr, int size){
// 使用heaptifyDown的原因是,如果使用 heaptifyUp从树的底部向上调整,每个节点在最坏情况下可能需要一直移到树的根部(并且底部的节点数量多)。
// 这意味着可能需要执行更多的比较和交换操作。而如果我们从上往下调整,每个节点最多只需要向下移动几层(通常是树的高度),这使得整体效率非常高。
for (int i = size / 2 - 1; i >= 0; i--) heaptifyDown(arr, size, i); // 从最后一个非叶子节点(size/2 - 1)开始,向上调整堆;
}
void heap_sort(float *heap, int size){ // 堆排序,从大道小排序
buildHeap( heap, size); // 构建小顶堆
while (size > 1) {
float tmp = heap[0]; heap[0] = heap[size - 1]; heap[size - 1] = tmp; size--; // 将堆顶元素与堆的最后一个元素交换,每次循环最小的元素被调整到末尾,堆的大小减1
heaptifyDown(heap, size, 0); // 从堆顶开始重新调整堆
}
freeHeap(&heap);
} |
Beta Was this translation helpful? Give feedback.
-
K神,文中代码注释提到【# 建堆操作:堆化除叶节点以外的其他所有节点】。为什么不堆化所有节点呢? |
Beta Was this translation helpful? Give feedback.
-
看到有人评论说还是不太理解这个过程,刚好我这里有个堆的可视化演示,可以直观看到过程 |
Beta Was this translation helpful? Give feedback.
-
请问手动实现需要掌握吗,还是会用java内置的priority queue就行了 |
Beta Was this translation helpful? Give feedback.
-
chapter_sorting/heap_sort/
一本动画图解、能运行、可提问的数据结构与算法入门书
https://www.hello-algo.com/chapter_sorting/heap_sort/
Beta Was this translation helpful? Give feedback.
All reactions