chapter_heap/build_heap/ #387
Replies: 24 comments 33 replies
-
写的好好啊 |
Beta Was this translation helpful? Give feedback.
-
建堆代码里面的逻辑不符合描述中的自顶至底的堆化过程 |
Beta Was this translation helpful? Give feedback.
-
时间复杂度的公式T(h) = 2 ^(h+1) - h,是不是少了 -2 呀? |
Beta Was this translation helpful? Give feedback.
-
看着数列头疼+1,还好写的详细 |
Beta Was this translation helpful? Give feedback.
-
个人觉得”我们先将列表所有元素原封不动添加到堆中,然后迭代地对各个节点执行“从顶至底堆化”。“这句话说的不是很清楚,我第一次学挺懵的,我觉得这样说更清晰一些: |
Beta Was this translation helpful? Give feedback.
-
请问大佬, maxHeap = new ArrayList<>(nums); 这里为什么还要创建一个ArrayList呢? |
Beta Was this translation helpful? Give feedback.
-
将列表所有元素原封不动添加到堆中,然后倒序遍历该堆,依次对每个节点执行“从顶至底堆化”。 |
Beta Was this translation helpful? Give feedback.
-
大佬大佬,那个c语言的建堆操作的代码里,for循环中int i=size-1的话不就是从最后一个叶节点开始了嘛,如果要是从最后一个非叶结点开始的话应该是int i=parent(size-1)吧,或者说还是我哪里理解错了呀 |
Beta Was this translation helpful? Give feedback.
-
8.2.1 自上而下构建: |
Beta Was this translation helpful? Give feedback.
-
一点小建议: 填充空堆: |
Beta Was this translation helpful? Give feedback.
-
应该注明,堆的高度 logN 是以(2叉树以2为底数,3叉以3为底)并且向上取整的值。 |
Beta Was this translation helpful? Give feedback.
-
借助入堆方法实现的时间复杂度不是应该是:$\sum_{i=1}^N \log i$ |
Beta Was this translation helpful? Give feedback.
-
我使用“借助入堆方法”实现建堆时,发现最终得到的结果和遍历堆化并不一致,具体实现: // 大顶堆
} let maxHeap = MaxHeap(nums: [1,2,3,4,5,6,7,8]) 输出结果:[8, 7, 6, 4, 3, 2, 5, 1] 从结果看两者都符合“大顶堆”,是否可以理解相同数据源,堆化结果并不是唯一的? |
Beta Was this translation helpful? Give feedback.
-
在复杂度分析里面“在从顶至底堆化的过程中,每个节点最多堆化到叶节点,因此最大迭代次数为二叉树高度 log n”。这里的n应该不是整个树的节点数量,而是堆化时子树的节点数。那么后面说的复杂度为O(nlog n)不准确就好理解啦。不知道我说的对不对🤣 |
Beta Was this translation helpful? Give feedback.
-
从最后一个非叶子节点一直到根结点进行类似下沉的堆化操作,时间复杂度是O(n),非常高效 |
Beta Was this translation helpful? Give feedback.
-
大佬,8.2.2 中建堆操作第二步为什么不能使用正序遍历(层序遍历),然后调用 siftUp 方法?这样根节点到当前节点中间的节点都是有效的(好像这个操作和 8.2.1 里的逻辑是一样的) |
Beta Was this translation helpful? Give feedback.
-
大佬关于第二种建堆方式的复杂度为O(n),我可以这样理解么: |
Beta Was this translation helpful? Give feedback.
-
假设完全二叉树的节点数量为 n ,则叶节点数量为最多为 (n+1)/2 ? |
Beta Was this translation helpful? Give feedback.
-
【我们首先创建一个空堆,然后遍历列表,依次对每个元素执行“入堆操作”,即先将元素添加至堆的尾部,再对该元素执行“从底至顶”堆化。】 |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
一个个插入,并保证堆结构,自上而下创建堆,是威廉姆斯提出的建堆算法时间复杂度为O(n*logn);从最后一个非叶子结点开始构建堆,不断进行堆化,自下而上创建堆,是弗洛伊德提出来的建堆算法,时间复杂度为O(n) |
Beta Was this translation helpful? Give feedback.
-
1.借助入堆操作实现建堆:"从底至顶”堆化,堆是“自上而下”构建的,建堆时间复杂度为O(nlogn) |
Beta Was this translation helpful? Give feedback.
-
大顶堆的初始化、建立、插入、出堆、释放的C语言版本代码 void initHeap(float **arr, int *size) { *arr = (float *)malloc(sizeof(float) * MAX_SIZE); *size = 0; } // 初始化堆的大小为0
void peekTop(float *arr, int size, float *x) { if (size <= 0) return ; *x = arr[0]; }
void getParent(int i, int *p_idx) { *p_idx = (i - 1) / 2; }
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 heaptifyUp(float *arr, int idx){
int cur = idx;
while (cur > 0){ // 只要 cur 不是根节点
int par; getParent(cur, &par); if (arr[cur] < arr[par]) break; // 如果当前节点小于父节点,退出循环
float tmp = arr[cur]; arr[cur] = arr[par]; arr[par] = tmp; cur = par; // 交换当前节点和父节点
}
}
void heaptifyDown(float *arr, int size, int idx){
int cur = idx;
while (true){
int lc, rc, maxidx = cur; getLeftChild(cur, &lc); getRightChild(cur, &rc);
if (lc < size && arr[lc] > arr[maxidx]) { maxidx = lc;} // 找到当前节点和左子节点中的最大值
if (rc < size && arr[rc] > arr[maxidx]) { maxidx = rc;} // 找到当前节点和右子节点中的最大值
if (maxidx == cur) break; // 如果当前节点是最大值,退出循环
float tmp = arr[cur]; arr[cur] = arr[maxidx]; arr[maxidx] = tmp; cur = maxidx; // 交换当前节点和最大值节点
}
}
void pushHeap(float *arr, int *size, float x){
if ((*size) >= MAX_SIZE) return; // 如果堆已满,直接返回
arr[*size] = x; (*size)++; // 将新元素放在堆的最后一个位置
heaptifyUp(arr, (*size) - 1); // 重新调整堆
}
void popHeap(float *arr, int *size, float *val){
if ((*size) <= 0) return; // 如果堆为空,直接返回
*val = arr[0];
arr[0] = arr[(*size) - 1]; // 将堆的最后一个元素放在堆顶
(*size)--;
heaptifyDown(arr, *size,0); // 重新调整堆
}
void freeHeap(float **arr) { if (*arr) { free(*arr); *arr = NULL; } } |
Beta Was this translation helpful? Give feedback.
-
通过堆化遍历来建立堆的C代码: void buildHeap(float *arr, int *heap_size, float *x, int size){
memcpy(arr, x, sizeof(float) * size); *heap_size = size; // 将数组x的元素复制到堆中
for (int i = size / 2 - 1; i >= 0; i--) heaptifyDown(arr, size, i); // 从最后一个非叶子节点开始,向上调整堆
} |
Beta Was this translation helpful? Give feedback.
-
chapter_heap/build_heap/
一本动画图解、能运行、可提问的数据结构与算法入门书
https://www.hello-algo.com/chapter_heap/build_heap/
Beta Was this translation helpful? Give feedback.
All reactions