最小堆的定义
最小堆是一颗完全二叉树,他的每一个节点的值不大于其左右子节点的值。
利用数组建立最小堆
leaf_name=['A','B','C','D','E','F','G','H'];
leaf_data=[10,1,1,11,1,1,8,5];
my_heap=heap();
my_heap.min_heap_create(leaf_name,leaf_data);
函数定义如下:
function heap = heap()
heap.size=0;
heap.name=[];
heap.data=[];
end
function min_heap_create(heap,name,data)
N=length(name);
for n=1:N
heap.name(n)=name(n);
heap.data(n)=data(n);
heap.size=heap.size +1;
end
end
运行结果如下:
node 1–>A–>10
node 2–>B–>1
node 3–>C–>1
node 4–>D–>11
node 5–>E–>1
node 6–>F–>1
node 7–>G–>8
node 8–>H–>5
图状表示如下:
节点下沉算法
因为最小堆的子树也是最小堆,所以可以从底部开始建立,采用节点下沉算法。如果子节点的值比本身小,将左右子节点中最小的一个和本身交换,相等的情况下左子节点优先交换。逐步下降,直到本身的节点不大于子节点停止。代码如下:
function heap_down_sink(heap,self)
lchild =self*2;
rchild =self*2+1;
if(lchild <= heap.size && rchild <= heap.size)
if(heap.data(self) > heap.data(lchild) || heap.data(self) > heap.data(rchild))
if(heap.data(lchild) <= heap.data(rchild))%左右子树相等的情况下,优先往左子树下沉
heap_swap_node(heap,lchild,self);
heap_down_sink(heap,lchild);
else
heap_swap_node(heap,rchild,self);
heap_down_sink(heap,rchild);
end
end
elseif(lchild <= heap.size)%仅仅只存在左叶子树
if(heap.data(self) > heap.data(lchild))
heap_swap_node(heap,lchild,self);
end
end
end
利用上面的节点下降算法调整二叉堆,使之满足最小堆的特性。方法是从最后一个节点开始,逐个运行节点下沉算法,就可以实现要求。函数如下:
function min_heap_adjust(heap)
n=heap.size;
while(n>=1)
heap_down_sink(heap,n)
n=n-1;
end
end
运行结果如下:
node 1–>B–>1
node 2–>E–>1
node 3–>C–>1
node 4–>H–>5
node 5–>A–>10
node 6–>F–>1
node 7–>G–>8
node 8–>D–>11
图状表示如下:
往最小堆中插入节点
插入节点不能破坏堆的特性,因此首先将堆的长度增加一个耽误,然后新增最后一个元素。因为只有新添加的节点可能不满足位置要求,因此对该节点执行上浮操作。具体做法是如果他的值小于其父母节点的值,那么交换两者的值,直到不满足条件为止,即可调整好最小堆。代码如下:
function min_heap_insert(heap,name,data)
%新增的节点添加的尾部
heap.size=heap.size +1;
heap.name(heap.size)=name;
heap.data(heap.size)=data;
%新增的节点做上浮的动作,达到排序的效果
heap_up_float(heap,heap.size);
end
function heap_up_float(heap,self)
while(self >=2)
parent=floor(self/2);
if(heap.data(self) < heap.data(parent))
heap_swap_node(heap,parent,self);
end
self =parent;
end
end
执行my_heap.min_heap_insert(‘N’,3)后,运行结果如下:
node 1–>B–>1
node 2–>E–>1
node 3–>C–>1
node 4–>N–>3
node 5–>A–>10
node 6–>F–>1
node 7–>G–>8
node 8–>D–>11
node 9–>H–>5
图状表示如下:
从最小堆里面弹出最小的节点
取出最小节点仍然不能破坏最小堆的结构,方法是将根节点和最后一个节点交换,那么最后一个节点就最小的节点。然后将堆的长度减小1个单位,此时只有根节点可能不满足最小堆的特性,执行节点下沉算法,就可以满足要求。代码如下:
function min_heap_popup(heap)
heap_swap_node(heap,1,heap.size);%交换根节点和尾结点
heap.size =heap.size -1;
heap_down_sink(heap,1);%根节点下沉
end
执行my_heap.min_heap_popup()后运算结果如下:
node 1–>E–>1
node 2–>N–>3
node 3–>C–>1
node 4–>H–>5
node 5–>A–>10
node 6–>F–>1
node 7–>G–>8
node 8–>D–>11
图状表示如下