最近在弄A*算法,大量的搜索最小值,发现只是普通的遍历会很卡,决定搞个二叉堆排序,简单的做个记录吧,有需要的可以参考下
用于A*算法中,应该是插入时排序,但是这里就直接对无序数组排序了。
首先第一步要构造堆,这里我们最终要的是升序,所以要构造大根堆,为了符合堆排序的定义,从下往上比较。每个数与其父节点进行比较,如果比父节点大,便和父节点进行交换,一直向上比较,直到小于等于父节点或者到达根节点了。
这时候我们就得到了一个大根堆,将根节点和末尾节点进行交换,然后再将剩余的数再构造成一个大根堆,因为此时只有根节点变换过,其余位置还是符合大根堆的构造,我们直接对根节点向下比较,再次得到大根堆,再进行首尾交换。。。。。
重复这个步骤,直到只剩根节点。
贴上代码:
function BinaryHeap(numbers)
for i = #numbers, 1, -1 do
parentIndex = math.floor(i/2)
currentIndex = i
while (numbers[parentIndex] ~= nil and numbers[currentIndex] > numbers[parentIndex]) do
Exchange(numbers, currentIndex, parentIndex)
currentIndex = parentIndex
parentIndex = math.floor(currentIndex/2)
end
end
lastIndex = #numbers
for i = 1, lastIndex do
currentIndex = 1
Exchange(numbers, currentIndex, lastIndex)
while (true) do
left = currentIndex * 2
if (left >= lastIndex) then
break
end
right = currentIndex * 2 + 1
if (right >= lastIndex) then
targetIndex = left
else
targetIndex = GetMaxChild(numbers,currentIndex * 2, currentIndex * 2 + 1)
end
if (numbers[currentIndex] < numbers[targetIndex]) then
Exchange(numbers, currentIndex, targetIndex)
else
break
end
currentIndex = targetIndex
end
lastIndex = lastIndex - 1
end
end
function GetMaxChild(numbers,left,right)
if (numbers[left] >= numbers[right]) then
return left
else
return right
end
end
function Exchange(numbers, a,b)
temp = numbers[a]
numbers[a] = numbers[b]
numbers[b] = temp
end
numbers = {2,4,7,5,3,10,23,44,265}
BinaryHeap(numbers)
print('Test')
for i = 1, #numbers do
print(numbers[i])
end
附上结果: