ViX*_*X28 8 arrays sorting algorithm heap
假设 MAX-HEAPIFY 操作。其中父元素值大于其子元素值。
siftDown 将一个太小的节点与其最大的子节点交换(从而将其向下移动),直到它至少与它下面的两个节点一样大。
siftUp 将一个太大的节点与其父节点交换(从而将其向上移动),直到它不大于其上方的节点。buildHeap 函数接受一个未排序项的数组并移动它们,直到它们都满足堆属性。
有两种方法可以用于 buildHeap。一种是从堆的顶部(数组的开头)开始,并在每个项目上调用 siftUp。在每一步,先前筛选的项目(数组中当前项目之前的项目)形成一个有效的堆,向上筛选下一个项目会将其放置在堆中的有效位置。筛选每个节点后,所有项目都满足堆属性。第二种方法则相反:从数组的末尾开始,然后向后向前移动。在每次迭代中,您筛选一个项目,直到它位于正确的位置。
让数组 a 有 5 个元素 a[4,2,3,5,6] 。
筛选-
输入- a[4,2,3,5,6]
加工-
从数组的开头应用 siftUp 操作。
siftUp(4) -
没有交换,因为它是根
heapified Array-a[4]
Run Code Online (Sandbox Code Playgroud)
筛选(2) -
没有交换,因为父值(4)更多
heapified Array-a[4,2]
Run Code Online (Sandbox Code Playgroud)
筛选(3) -
没有交换,因为父值(4)更多
heapified Array-a[4,2,3]
Run Code Online (Sandbox Code Playgroud)
筛选(5) -
它的父值是 2 所以交换 (5,2)。
Array-a[4,5,3,2]
Run Code Online (Sandbox Code Playgroud)
现在 5 的父值是 4,所以再次交换 (5,4)。
heapified Array-a[5,4,3,2]
Run Code Online (Sandbox Code Playgroud)
筛选(6) -
首先在 (6,4) 之间交换,然后在 (6,5) 之间交换
heapified Array-a[6,5,3,2,4]
Run Code Online (Sandbox Code Playgroud)
输出-a[6,5,3,2,4]
筛选-
输入- a[4,2,3,5,6]
加工-
从数组的末尾,我们将一一应用 siftDown 操作。
筛选(6) -
它没有孩子所以没有交换。同样适用于 siftDown(5) 和 siftDown(3) 也因为他们没有任何孩子。所以他们不能进一步向下移动。
到现在为止的数组 - a[4,2,3,5,6]
筛选(2) -
它与较大的子值交换。这里 6 是较大的一个。所以交换(2,6)。
现在数组将是 -a[4,6,3,5,2]
筛选 (4) -
4 有两个孩子 6 和 3。与较大的交换。交换(4,6)完成。现在数组将是- a[6,4,3,5,2]
再次 4 必须交换,因为它有一个大于它自己的孩子,即 5 。这样交换(4,5)就完成了。
数组将是 - a[6,5,3,4,2]
堆化数组 -a[6,5,3,4,2]
输出-a[6,5,3,4,2]
为什么在对同一组元素执行 siftUp 和 siftDown 操作时会得到两个不同的输出?或者,当 siftUp 和 siftDown 应用于同一组元素时,可能会有不同的堆。请说清楚。:)
是的,同一组元素可以有不同的堆。
两种方法都能正确生成满足堆属性的堆:父元素值大于其子元素值。
第一种方法:
6
/ \
5 3
/ \
2 4
Run Code Online (Sandbox Code Playgroud)
第二种方法:
6
/ \
5 3
/ \
4 2
Run Code Online (Sandbox Code Playgroud)
事实上,如果你用手画的话,还有其他可能的堆,例如
6
/ \
4 5
/ \
2 3
Run Code Online (Sandbox Code Playgroud)
但请注意,这两种方法虽然都能生成正确的结果,但它们具有不同的复杂性。请参阅构建堆的时间复杂度如何达到 O(n)?。