最小堆的含义就不多比比了。最小堆可以应用于排序 ,详情可以参考文章 堆排序 。
最小堆的基本函数包括:构造堆,调整堆,弹出堆顶元素,添加一个元素。
目录
一、数组结构的最小堆
1.向下调整堆
2.构造堆
3.弹出堆顶元素
4.添加新元素
二、结构体结构的最小堆
三、元胞数组结构的最小堆
本文使用数组a表示一个堆。a(1)是堆顶元素。a(2*i) 和 a(2*i+1) 分别是 a(i) 的左右孩子。
从节点 i 开始向下调整,与其左右孩子比较大小,如果左或右孩子值比它小,就交换他们的位置,然后向下迭代。
function a = shiftdown(a,i)
n = length(a);
if 2*i <= n && 2*i+1 <= n && i <= n %节点 i 左右孩子都有
if a(i) > a(2*i)
a = swap(a,i,2*i);
a = shiftdown(a,2*i);
end
if a(i) > a(2*i+1)
a = swap(a,i,2*i+1);
a = shiftdown(a,2*i+1);
end
elseif 2*i <= n %节点 i 只有左孩子
if a(i) > a(2*i)
a = swap(a,i,2*i);
a = shiftdown(a,2*i);
end
end
end
从底层节点(非叶子节点)开始往上构造。
% 构造一个最小堆
function a = make_heap(a)
n = length(a);
for i = n/2:-1:1
a = shiftdown(a,i);
end
end
删除堆顶元素,然后从新堆顶开始向下调整。
% 弹出堆顶元素
function a = pop(a)
a(1) = [];
n = length(a);
a = shiftdown(a,1);
end
将新元素添加至数组末尾,然后向上调整。
%添加一个元素
function a = push(a,value)
a(end+1) = value;
n = length(a);
while n>=2
parent = floor(n/2);
if a(n) < a(parent);
a = swap(a,parent,n);
end
n = parent;
end
end
有问题或者文章有错误,欢迎提问或指教,评论区欢迎您。 白嫖请点个赞,谢谢!
***************************************华丽的分割线********************************************************
更新: 结构体数组的最小堆。结构体有两个属性( 'id' , 'd' )。 根据属性 “d” 构造最小堆。
a = [19,14,5,3,27,18,19,22,11,2];
b = [];
for i = 1:length(a)
b(i).id = i;
b(i).d = a(i);
end
c = make_heap(b)
function a = swap(a,i,j) %交换数组的两个元素
t = a(i);
a(i) = a(j);
a(j) = t;
end
% 向下调整函数
function a = shiftdown(a,i)
n = length(a);
if 2*i <= n && 2*i+1 <= n && i <= n
if a(i).d > a(2*i).d
a = swap(a,i,2*i);
a = shiftdown(a,2*i);
end
if a(i).d > a(2*i+1).d
a = swap(a,i,2*i+1);
a = shiftdown(a,2*i+1);
end
elseif 2*i <= n
if a(i).d > a(2*i).d
a = swap(a,i,2*i);
a = shiftdown(a,2*i);
end
end
end
% 构造一个最小堆
function a = make_heap(a)
n = length(a);
for i = n/2:-1:1
a = shiftdown(a,i);
end
end
% 弹出堆顶元素
function a = pop(a)
a(1) = [];
n = length(a);
a = shiftdown(a,1);
end
%添加一个元素
function a = push(a,id,value)
n = length(a)+1;
a(n).id = id;
a(n).d = value;
n = length(a);
while n>=2
parent = floor(n/2);
if a(n).d < a(parent).d;
a = swap(a,parent,n);
end
n = parent;
end
end
***************************************华丽的分割线********************************************************
更新: 元胞数组数组的最小堆。元胞数组元素有两个值。 根据元素第二个值的大小构造最小堆。
a = [19,14,5,3,27,18,19,22,11,2];
n = 10;
no = {}; %根据数组构造元胞数组no ,no元素的第一个值是a元素的下标,第二个值是a元素值
for i = 1:10
no{i} = {i;a(i)};
end
c = make_heap(no);
c
function a = swap(a,i,j) %交换数组的两个元素
t = a{i};
a{i} = a{j};
a{j} = t;
end
% 向下调整函数
function a = shiftdown(a,i)
n = length(a);
if 2*i <= n && 2*i+1 <= n && i <= n
if cell2mat(a{i}(2)) > cell2mat(a{2*i}(2))
a = swap(a,i,2*i);
a = shiftdown(a,2*i);
end
if cell2mat(a{i}(2)) > cell2mat(a{2*i+1}(2))
a = swap(a,i,2*i+1);
a = shiftdown(a,2*i+1);
end
elseif 2*i <= n
if cell2mat(a{i}(2)) > cell2mat(a{2*i}(2))
a = swap(a,i,2*i);
a = shiftdown(a,2*i);
end
end
end
% 构造一个最小堆
function a = make_heap(a)
n = length(a);
for i = n/2:-1:1
a = shiftdown(a,i);
end
end
% 弹出堆顶元素
function a = pop(a)
a(1) = [];
n = length(a);
a = shiftdown(a,1);
end
%添加一个元素
function a = push(a,id,value)
n = length(a)+1;
a{n} = {id;value};
n = length(a);
while n>=2
parent = floor(n/2);
if cell2mat(a{n}(2)) < cell2mat(a{parent}(2))
a = swap(a,parent,n);
end
n = parent;
end
end