当我使用heapsort
实现min-heap
时,它会将数组从最大到最小排序。这是使用heapsort
的{{1}}所需的输出吗?由于min-heap
本身具有从最小到最大的结构,因此在排序完成后再次排序以输出最小到最大似乎是多余的。
CODE:
heap
代码输出:
#include <iostream>
#include <vector>
#include "random.h"
#include "print.h"
int parent(int i)
{
return (i - 1) / 2;
}
int left(int i)
{
if(i == 0)
return 1;
else
return 2*i;
}
int right(int i)
{ if(i == 0)
return 2;
else
return 2*i + 1;
}
void min_heapify(std::vector<int> &A, int i, int heapsize)
{
int smallest;
int l = left(i);
//std::cout << "left = " << l << std::endl;
int r = right(i);
//std::cout << "right = " << r << std::endl;
if(l <= heapsize && A[l] < A[i])
smallest = l;
else
smallest = i;
//std::cout << "smallest = " << smallest << std::endl;
if(r <= heapsize && A[r] < A[smallest])
smallest = r;
if(smallest != i) {
print(A);
exchange(A, i, smallest);
min_heapify(A, smallest, heapsize);
}
}
void build_min_heap(std::vector<int> &A)
{
int heapsize = A.size() - 1;
for(int i = (A.size() - 1) / 2; i >= 0; i--)
min_heapify(A, i, heapsize);
}
void heapsort(std::vector<int> &A)
{
int heapsize = A.size() - 1;
build_min_heap(A);
std::cout << "heapsort after buildmaxheap" << std::endl;
print(A);
for(int i = A.size() - 1; i > 0; i--) {
exchange(A, 0, i);
heapsize--;
std::cout << "heapsize = " << heapsize << std::endl;
min_heapify(A, 0, heapsize);
}
}
int main()
{
std::vector<int> B;
fill(B, 5);
print(B);
heapsort(B);
print(B);
return 0;
}
20个元素的输出:
41 65 31 41 19
41 65 31 41 19
41 65 19 41 31
41 19 65 41 31
41 19 31 41 65
19 41 31 41 65
heapsort after buildmaxheap
19 31 41 41 65
heapsize = 3
65 31 41 41 19
31 65 41 41 19
heapsize = 2
heapsize = 1
65 41 41 31 19
heapsize = 0
65 41 41 31 19
答案 0 :(得分:2)
订单:使用max-heapify按升序排序,min-heapify按降序排序。
排序:使用min-heapify构建堆不会对数组进行排序;它只强制执行(弱)min-heap属性,即
A[parent(i)] <= A[i]
对于除根之外的每个节点i
。构建堆之后,根(数组中最左边的位置)具有最小元素。然后排序然后重复地从根向右移动元素并在根上调用min-heapify(将剩余的最小值留在那里),因此降序。
您发布的代码看起来是正确的,但不能按原样编译,所以我无法测试。如果您的数组在构建堆后立即显示排序,则应该是巧合。尝试更大的测试。
答案 1 :(得分:1)
我只是想知道这个问题(不是Heap排序在最后有一个额外的步骤,不必要的元素交换。只需使用min-heaps并调用min-heapify
并完成工作) 。
关于这种方式,我们可以实现O(logn)时间,这有时会使二元决策树模型失去资格 - 这表示O(nlogn)在比较排序算法上是可接受的最严格上限。
简短的回答是:堆数据结构不是二叉搜索树。堆可以保证按排序的top-&gt; bottom方式排序元素,但是二进制搜索树保证它们也将从左到右排序。我们只是混合了二叉树和堆。
最小堆只保证,
Amin[Parent]<=A[either_of_the_children] // says nothing about ordering of children
这是一个二叉树(虽然不平衡但没有排序):
这是一堆:
希望你明白我的观点。如果还没有,那么把它想象成一个最小的堆表示一个数组保证父级小于它的子级,但是没有说明所有的子项是按从左到右的排序顺序排列的吗? 我们仍然会对要交换的当前root的每个子节点执行min-heapify。
答案 2 :(得分:0)
通常使用max-heap按升序排序,因为它更容易。 使用max-heap,你将'max'浮动到前面,然后从后面构建排序列表。
如果要使用最小堆按升序排序,则必须向后构建它。 (即最低是最后一个索引)。否则你会搅动你的堆。
start 18 70 6 13 12 55
min-heap(backwards) -> 18 70 55 13 12 6
then
swap 6 w 18 -> 6, 70 55 13 12 18 -> sink 18 -> 70 55 13 18 12
swap 12 w 70 -> 6 12, 55 13 18 70 -> sink 70 -> 55 70 18 13
swap 13 w 55 -> 6 12 13, 70 18 55 -> sink 55 -> 70 55 18
swap 18 w 70 -> 6 12 13 18, 55 70 -> sink 70 -> 70 55
swap 55 w 70 -> 6 12 13 18 55, 70
done