erl_tree heap 堆实现

来源:互联网 发布:云计算系统软件 编辑:程序博客网 时间:2024/06/05 20:45

erlang heap 堆实现

要说最大堆和最小堆,就得先知道最大树和最小树。
每个结点的值都大于(小于)或等于其子节点(如果有的话)值的树,就叫最大(最小)树。
最大堆(最小堆)是最大(最小)完全树。
由于堆是完全二叉树,所以可以用公式化描述,用一维数组来有效的描述堆结构。
利用二叉树的性质:
如果对一棵有n个结点的完全二叉树的结点按层序编号(从第1层到第[log2n]向下取整+1层,每层从左到右),则对任一结点i(1≤i≤n),有:
(1)如果i=1,则结点i无双亲,是二叉树的根;如果i>1,则其双亲是结点[i/2]向下取整。
(2)如果2i>n,则结点i为叶子结点,无左孩子;否则,其左孩子是结点2i。
(3)如果2i+1>n,则结点i无右孩子;否则,其右孩子是结点2i+1。
这样就就可以将堆中结点移到它的父节点或者其中一个子节点处。
堆中进行的操作主要是:插入,删除,以及初始化。
这里写图片描述

以下代码用tuple实现了最大最小堆,要转换只需修改一下?HEAP_TYPE 成max.

代码

%% Copyright-module(tuple_heap).-author("sugar").%% API-compile(export_all).%% 最小堆 min 最大堆 max-define(HEAP_TYPE, min ).-define(CMP(V1,V2),case ?HEAP_TYPE of min-> ?MINCMP(V1,V2); _ -> ?MAXCMP(V1,V2) end).%%最小堆-define(MINCMP(V1,V2), V1 < V2 ).%%最大堆-define(MAXCMP(V1,V2), V1 < V2 ).get_size(Heap)-> erlang:tuple_size(Heap).%% 获取父节点parent(Index)-> trunc(Index / 2).%% 获取左孩子left(Index)-> 2*Index.%%获取右孩子right(Index)-> 2*Index+1.get_top(Heap)-> case get_size(Heap) of  0->   error("heap empty !");  _ ->   erlang:element(1,Heap) end.%%插入insert(V,Heap)-> NewHeap = erlang:append_element(Heap,V), NewSize = get_size(NewHeap), if NewSize == 1 ->   NewHeap;  true->   Parent = erlang:element(parent(NewSize),NewHeap),   case ?CMP(V , Parent) of    true->     move_up(NewHeap,NewSize);    _->     NewHeap   end end.%%取出%%return {minData,newHeap}pop(Heap)-> Size = get_size(Heap), Min = erlang:element(1,Heap), Last = erlang:element(Size,Heap), Heap1 = erlang:delete_element(Size,Heap), Heap2 = erlang:setelement(1,Heap1,Last), Heap3 = move_down(Heap2,1), {Min,Heap3}.move_up(Heap,1)-> Heap;move_up(Heap,Index)-> Cur = erlang:element(Index,Heap), Pindex = parent(Index), Parent = erlang:element(Pindex,Heap), case ?CMP(Cur , Parent) of  true->   Heap1 = erlang:setelement(Pindex,Heap,Cur),   Heap2 = erlang:setelement(Index,Heap1,Parent),   move_up(Heap2,Pindex);  _->   Heap end.move_down(Heap,Index)-> Size = get_size(Heap), Cur = erlang:element(Index,Heap), TIndex = case ?HEAP_TYPE of max-> right(Index); _-> left(Index) end, ToV = if TIndex =< Size-> erlang:element(TIndex,Heap);  true-> undefined end, ToVIsint = erlang:is_integer(ToV), case ToVIsint andalso ?CMP(ToV , Cur) of  true->   Heap1 = erlang:setelement(TIndex,Heap,Cur),   Heap2 = erlang:setelement(Index,Heap1,ToV),   move_down(Heap2,TIndex);  _-> Heap end.
0 0
原创粉丝点击