二叉堆本质上是一种完全二叉树:
当二叉堆插入节点时,插入位置是完全二叉树的最后一个位置。例如插入一个新节点,值是 0。
这时,新节点的父节点5比0大,显然不符合最小堆的性质。于是让新节点“上 浮”,和父节点交换位置。直到最后。
下面举一个无序完全二叉树的例子:
Class PHA.YX.Arithmetic.Heap Extends %RegisteredObject
{
/* 自定义数据有问题,不知道为啥不行,提示非法值 */
Method upAdjust(array)
{
#dim childIndex as %Integer = array.length() - 1
s resutlt = (childIndex - 1 ) / 2
#dim parentIndex as %Integer = +resutlt
#dim temp as %Integer = array.get(childIndex)
while((childIndex > 0)&&(temp < array.get(parentIndex))){
w temp,!
s array.get(childIndex) = array.get(parentIndex)
s childIndex = parentIndex
s parentIndex = (parentIndex - 1) / 2
}
s array.get(childIndex) = temp
}
/// 上浮调整
Method upAdjustArray(array As %ArrayOfDataTypes)
{
#dim childIndex as %Integer = array.Count() - 1
#dim parentIndex as %Integer = (childIndex - 1 ) \ 2 /* 这一定要取整数 */
/* temp保存插入的叶子节点值,用于最后的赋值 */
#dim temp as %Integer = array.GetAt(childIndex)
while((childIndex > 0)&&(temp < array.GetAt(parentIndex))){
/* 无需真正交换,单向赋值即可 */
d array.SetAt(array.GetAt(parentIndex),childIndex)
s childIndex = parentIndex
s parentIndex = (parentIndex - 1) \ 2
}
d array.SetAt(temp,childIndex)
q array
}
/// 下沉调整
Method downAjustArray(array As %ArrayOfDataTypes, parentIndex As %Integer, length As %Integer)
{
#dim temp as %Integer = array.GetAt(parentIndex)
#dim childIndex as %Integer = 2 * parentIndex + 1
while(childIndex < length){
;w "childIndex i:"_childIndex _ " array.GetAt(childIndex + 1):" _array.GetAt(childIndex + 1)_ " array.GetAt(childIndex):" _array.GetAt(childIndex),!
/* 如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子 */
if (((childIndex + 1) < length)&&(array.GetAt(childIndex + 1) < array.GetAt(childIndex))){
s childIndex = childIndex + 1
}
;b:temp=1
;w "temp:"_temp _ " array.GetAt(childIndex):"_array.GetAt(childIndex),!
;w "childIndex:"_childIndex,!
;w array.GetAt(childIndex),!
/* 如果父节点小于任何一个孩子的值,直接跳出 */
if (temp <= array.GetAt(childIndex)){
quit /* 这一定是quit 而不是continue */
}
/* 无需真正交换,单向赋值即可 */
d array.SetAt(array.GetAt(childIndex), parentIndex)
s parentIndex = childIndex
s childIndex = 2 * childIndex + 1
}
d array.SetAt(temp, parentIndex)
}
/// 构建堆
Method buildHeap(array As %ArrayOfDataTypes)
{
/* 从最后一个非叶子节点开始,依次下沉调整 */
f i = (array.Count() - 2) \ 2 : -1 : 0 d
.;w "i:"_ i,!
.d ..downAjustArray(array,i,array.Count())
q array
}
}
/// w ##class(PHA.YX.Arithmetic).HeapArray()
ClassMethod HeapArray()
{
s array = ##class(%ArrayOfDataTypes).%New()
d array.SetAt(1,0)
d array.SetAt(3,1)
d array.SetAt(2,2)
d array.SetAt(6,3)
d array.SetAt(5,4)
d array.SetAt(7,5)
d array.SetAt(8,6)
d array.SetAt(9,7)
d array.SetAt(10,8)
d array.SetAt(0,9)
#dim mHeap as PHA.YX.Arithmetic.Heap = ##class(PHA.YX.Arithmetic.Heap).%New()
s array = mHeap.upAdjustArray(array)
zw array
d array.Clear()
zw array
d array.SetAt(7,0)
d array.SetAt(1,1)
d array.SetAt(3,2)
d array.SetAt(10,3)
d array.SetAt(5,4)
d array.SetAt(2,5)
d array.SetAt(8,6)
d array.SetAt(9,7)
d array.SetAt(6,8)
zw array
s array = mHeap.buildHeap(array)
zw array
q ""
}
DHC-APP> w ##class(PHA.YX.Arithmetic).HeapArray()
array=