dets_utils.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,580 行 · 第 1/4 页
ERL
1,580 行
K == Key -> % Replace (?). bplus_insert_in_leaf_3(Leaf, N-1, [ Key|Accum]) end.bplus_insert_in_leaf_3(_Leaf, 0, LeafList) -> bplus_mk_leaf(LeafList);bplus_insert_in_leaf_3(Leaf, N, LeafList) -> bplus_insert_in_leaf_3(Leaf, N-1, [?GET_LEAF_KEY(Leaf, N)|LeafList]).%%% -------------------------%%% Help functions for delete.%%% -------------------------bplus_delete_in(Tree, Key) -> case ?NODE_TYPE(Tree) of l -> bplus_delete_in_leaf(Tree, Key); n -> {Pos, SubTree} = bplus_select_sub_tree(Tree, Key), % Pos = "the position of the subtree". NewSubTree = bplus_delete_in(SubTree, Key), % Check if it has become to small now case ?UNDER_FILLED(NewSubTree) of false -> bplus_put_subtree(Tree, [NewSubTree, Pos]); true -> case bplus_reorganize_tree_del(Tree, NewSubTree, Pos) of {left, {LeftT, DKey, MiddleT}} -> bplus_put_subtree(bplus_put_lkey(Tree, DKey, Pos), [LeftT, Pos-1, MiddleT, Pos]); {right, {MiddleT, DKey, RightT}} -> bplus_put_subtree(bplus_put_rkey(Tree, DKey, Pos), [MiddleT, Pos, RightT, Pos+1]); {join_left, JoinedTree} -> bplus_joinleft_tree(Tree, JoinedTree, Pos); {join_right, JoinedTree} -> bplus_joinright_tree(Tree, JoinedTree, Pos) end end end.%%-----------------------------------------------------------------%% Deletes a key from the leaf returning a new (smaller) leaf.%%-----------------------------------------------------------------bplus_delete_in_leaf(Leaf, Key) -> bplus_delete_in_leaf_2(Leaf, Key, bplus_get_size(Leaf), []).bplus_delete_in_leaf_2(Leaf, _, 0, _) -> Leaf;bplus_delete_in_leaf_2(Leaf, Key, N, Accum) -> K = ?GET_LEAF_KEY(Leaf, N), if Key == K -> % Remove this one! bplus_delete_in_leaf_3(Leaf, N-1, Accum); true -> bplus_delete_in_leaf_2(Leaf, Key, N-1, [K|Accum]) end.bplus_delete_in_leaf_3(_Leaf, 0, LeafList) -> bplus_mk_leaf(LeafList);bplus_delete_in_leaf_3(Leaf, N, LeafList) -> bplus_delete_in_leaf_3(Leaf, N-1, [?GET_LEAF_KEY(Leaf, N)|LeafList]).%%-----------------------------------------------------------------%% Selects and returns which subtree the search should continue in.%%-----------------------------------------------------------------bplus_select_sub_tree(Tree, Key) -> bplus_select_sub_tree_2(Tree, Key, bplus_get_size(Tree)).bplus_select_sub_tree_2(Tree, _Key, 1) -> {1, bplus_get_tree(Tree, 1)};bplus_select_sub_tree_2(Tree, Key, N) -> K = bplus_get_lkey(Tree, N), if K > Key -> bplus_select_sub_tree_2(Tree, Key, N-1); K =< Key -> % Here it is! {N, bplus_get_tree(Tree, N)} end.%%-----------------------------------------------------------------%% Selects which brother that should take over some of our items.%% Or if they are both full makes a split.%%-----------------------------------------------------------------bplus_reorganize_tree_ins(Tree, NewSubTree, 1) -> RTree = bplus_get_tree(Tree, 2), % 2 = Pos+1 = 1+1. case ?FULL(RTree) of false -> bplus_reorganize_tree_r(Tree, NewSubTree, 1, RTree); true -> % It is full, we must split this one! bplus_reorganize_tree_s(NewSubTree) end;bplus_reorganize_tree_ins(Tree, NewSubTree, Pos) -> Size = bplus_get_size(Tree), if Pos == Size -> % Pos is the rightmost postion!. % Our only chance is the left one. LTree = bplus_get_tree(Tree, Pos-1), case ?FULL(LTree) of false -> bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree); true -> % It is full, we must split this one! bplus_reorganize_tree_s(NewSubTree) end; true -> % Pos is somewhere inside the node. LTree = bplus_get_tree(Tree, Pos-1), RTree = bplus_get_tree(Tree, Pos+1), SL = bplus_get_size(LTree), SR = bplus_get_size(RTree), if SL > SR -> bplus_reorganize_tree_r(Tree, NewSubTree, Pos, RTree); SL < SR -> bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree); true -> case ?FULL(LTree) of false -> bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree); true -> bplus_reorganize_tree_s(NewSubTree) end end end.%%-----------------------------------------------------------------%% This function fills over items from brothers to maintain the minimum%% number of items per node/leaf.%%-----------------------------------------------------------------bplus_reorganize_tree_del(Tree, NewSubTree, 1) -> % The case when Pos is at leftmost position. RTree = bplus_get_tree(Tree, 2), % 2 = Pos+1 = 1+1. case ?LOW_FILLED(RTree) of false -> bplus_reorganize_tree_r(Tree, NewSubTree, 1, RTree); true -> % It is to small, we must join them! bplus_reorganize_tree_jr(Tree, NewSubTree, 1, RTree) end;bplus_reorganize_tree_del(Tree, NewSubTree, Pos) -> Size = bplus_get_size(Tree), if Pos == Size -> % Pos is the rightmost postion!. % Our only chance is the left one. LTree = bplus_get_tree(Tree, Pos-1), case ?LOW_FILLED(LTree) of false -> bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree); true -> % It is to small, we must join this one! bplus_reorganize_tree_jl(Tree, NewSubTree, Pos, LTree) end; true -> % Pos is somewhere inside the node. LTree = bplus_get_tree(Tree, Pos-1), RTree = bplus_get_tree(Tree, Pos+1), SL = bplus_get_size(LTree), SR = bplus_get_size(RTree), if SL>SR -> bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree); SL < SR -> bplus_reorganize_tree_r(Tree, NewSubTree, Pos, RTree); true -> case ?LOW_FILLED(LTree) of false -> bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree); true -> bplus_reorganize_tree_jl(Tree, NewSubTree, Pos, LTree) end end end.bplus_reorganize_tree_l(Tree, NewSubTree, Pos, LTree) -> case ?NODE_TYPE(NewSubTree) of l -> {left, bplus_split_leaf( bplus_mk_leaf( lists:append(bplus_leaf_to_list(LTree), bplus_leaf_to_list(NewSubTree))))}; n -> {left, bplus_split_node( bplus_mk_node( lists:append([bplus_node_to_list(LTree), [bplus_get_lkey(Tree, Pos)], bplus_node_to_list(NewSubTree)])))} end.bplus_reorganize_tree_r(Tree, NewSubTree, Pos, RTree) -> case ?NODE_TYPE(NewSubTree) of l -> {right, bplus_split_leaf( bplus_mk_leaf( lists:append([bplus_leaf_to_list(NewSubTree), bplus_leaf_to_list(RTree)])))}; n -> {right, bplus_split_node( bplus_mk_node( lists:append([bplus_node_to_list(NewSubTree), [bplus_get_rkey(Tree, Pos)], bplus_node_to_list(RTree)])))} end.bplus_reorganize_tree_s(NewSubTree) -> case ?NODE_TYPE(NewSubTree) of l -> {split, bplus_split_leaf(NewSubTree)}; n -> {split, bplus_split_node(NewSubTree)} end.bplus_reorganize_tree_jl(Tree, NewSubTree, Pos, LTree) -> case ?NODE_TYPE(NewSubTree) of l -> {join_left, bplus_mk_leaf(lists:append([bplus_leaf_to_list(LTree), bplus_leaf_to_list(NewSubTree)]))}; n -> {join_left, bplus_mk_node(lists:append([bplus_node_to_list(LTree), [bplus_get_lkey(Tree, Pos)], bplus_node_to_list(NewSubTree)]))} end.bplus_reorganize_tree_jr(Tree, NewSubTree, Pos, RTree) -> case ?NODE_TYPE(NewSubTree) of l -> {join_right, bplus_mk_leaf(lists:append([bplus_leaf_to_list(NewSubTree), bplus_leaf_to_list(RTree)]))}; n -> {join_right, bplus_mk_node(lists:append([bplus_node_to_list(NewSubTree), [bplus_get_rkey(Tree, Pos)], bplus_node_to_list(RTree)]))} end.%%-----------------------------------------------------------------%% Takes a leaf and divides it into two equal big leaves.%% The result is returned in a tuple. The dividing key is also returned.%%-----------------------------------------------------------------bplus_split_leaf(Leaf) -> S = bplus_get_size(Leaf), bplus_split_leaf_2(Leaf, S, S div 2, []).bplus_split_leaf_2(Leaf, Pos, 1, Accum) -> K = ?GET_LEAF_KEY(Leaf, Pos), bplus_split_leaf_3(Leaf, Pos-1, [], K, [K|Accum]);bplus_split_leaf_2(Leaf, Pos, N, Accum) -> bplus_split_leaf_2(Leaf, Pos-1, N-1, [?GET_LEAF_KEY(Leaf, Pos)|Accum]).bplus_split_leaf_3(_, 0, LeftAcc, DKey, RightAcc) -> {bplus_mk_leaf(LeftAcc), DKey, bplus_mk_leaf(RightAcc)};bplus_split_leaf_3(Leaf, Pos, LeftAcc, DKey, RightAcc) -> bplus_split_leaf_3(Leaf, Pos-1, [?GET_LEAF_KEY(Leaf, Pos)|LeftAcc], DKey, RightAcc).%%-----------------------------------------------------------------%% Takes a node and divides it into two equal big nodes.%% The result is returned in a tuple. The dividing key is also returned.%%-----------------------------------------------------------------bplus_split_node(Node) -> S = bplus_get_size(Node), bplus_split_node_2(Node, S, S div 2, []).bplus_split_node_2(Node, Pos, 1, Accum) -> bplus_split_node_3(Node, Pos-1, [], bplus_get_lkey(Node, Pos), [bplus_get_tree(Node, Pos)|Accum]);bplus_split_node_2(Node, Pos, N, Accum) -> bplus_split_node_2(Node, Pos-1, N-1, [bplus_get_lkey(Node, Pos), bplus_get_tree(Node, Pos)|Accum]).bplus_split_node_3(Node, 1, LeftAcc, DKey, RightAcc) -> {bplus_mk_node([bplus_get_tree(Node, 1)|LeftAcc]), DKey, bplus_mk_node(RightAcc)};bplus_split_node_3(Node, Pos, LeftAcc, DKey, RightAcc) -> bplus_split_node_3(Node, Pos-1, [bplus_get_lkey(Node, Pos), bplus_get_tree(Node, Pos)|LeftAcc], DKey, RightAcc).%%-----------------------------------------------------------------%% Inserts a joined tree insted of the old one at position Pos and%% the one nearest left/right brother.%%-----------------------------------------------------------------bplus_joinleft_tree(Tree, JoinedTree, Pos) -> bplus_join_tree_2(Tree, JoinedTree, Pos, bplus_get_size(Tree), []).bplus_joinright_tree(Tree, JoinedTree, Pos) -> bplus_join_tree_2(Tree, JoinedTree, Pos+1, bplus_get_size(Tree), []).bplus_join_tree_2(Tree, JoinedTree, Pos, Pos, Accum) -> bplus_join_tree_3(Tree, Pos-2, [JoinedTree|Accum]);bplus_join_tree_2(Tree, JoinedTree, Pos, N, Accum) -> bplus_join_tree_2(Tree, JoinedTree, Pos, N-1, [bplus_get_lkey(Tree, N), bplus_get_tree(Tree, N)|Accum]).bplus_join_tree_3(_Tree, 0, Accum) -> bplus_mk_node(Accum);bplus_join_tree_3(Tree, Pos, Accum) -> bplus_join_tree_3(Tree, Pos-1, [bplus_get_tree(Tree, Pos), bplus_get_rkey(Tree, Pos)|Accum]).%%% ---------------------------------%%% Primitive datastructure functions.%%% ---------------------------------%%-----------------------------------------------------------------%% Constructs a node out of list format.%%-----------------------------------------------------------------bplus_mk_node(NodeList) -> list_to_tuple([ n |NodeList]).%%-----------------------------------------------------------------%% Converts the node into list format.%%-----------------------------------------------------------------bplus_node_to_list(Node) -> [_|NodeList] = tuple_to_list(Node), NodeList.%%-----------------------------------------------------------------%% Constructs a leaf out of list format.%%-----------------------------------------------------------------bplus_mk_leaf(KeyList) -> list_to_tuple([l|KeyList]).%%-----------------------------------------------------------------%% Converts a leaf into list format.%%-----------------------------------------------------------------bplus_leaf_to_list(Leaf) -> [_|LeafList] = tuple_to_list(Leaf), LeafList.%%-----------------------------------------------------------------%% Changes subtree "pointers" in a node.%%-----------------------------------------------------------------bplus_put_subtree(Tree, []) -> Tree;bplus_put_subtree(Tree, [NewSubTree, Pos|Rest]) -> bplus_put_subtree(setelement(Pos*2, Tree, NewSubTree), Rest).%%-----------------------------------------------------------------%% Replaces the tree at position Pos with two new trees.%%-----------------------------------------------------------------bplus_extend_tree(Tree, Inserts, Pos) -> bplus_extend_tree_2(Tree, Inserts, Pos, bplus_get_size(Tree), []).bplus_extend_tree_2(Tree, {T1, DKey, T2}, Pos, Pos, Accum) -> bplus_extend_tree_3(Tree, Pos-1, [T1, DKey, T2|Accum]);bplus_extend_tree_2(Tree, Inserts, Pos, N, Accum) -> bplus_extend_tree_2(Tree, Inserts, Pos, N-1, [bplus_get_lkey(Tree, N), bplus_get_tree(Tree, N)|Accum]).bplus_extend_tree_3(_, 0, Accum) -> bplus_mk_node(Accum);bplus_extend_tree_3(Tree, N, Accum) -> bplus_extend_tree_3(Tree, N-1, [bplus_get_tree(Tree, N), bplus_get_rkey(Tree, N)|Accum]).%%-----------------------------------------------------------------%% Changes the dividing key between two trees.%%-----------------------------------------------------------------bplus_put_lkey(Tree, DKey, Pos) -> setelement(Pos*2-1, Tree, DKey).bplus_put_rkey(Tree, DKey, Pos) -> setelement(Pos*2+1, Tree, DKey).%%-----------------------------------------------------------------%% Calculates the number of items in a node/leaf.%%-----------------------------------------------------------------bplus_get_size(Tree) -> case ?NODE_TYPE(Tree) of l -> size(Tree)-1; n -> size(Tree) div 2 end.%%-----------------------------------------------------------------%% Returns a tree at position Pos from an internal node.%%-----------------------------------------------------------------bplus_get_tree(Tree, Pos) -> element(Pos*2, Tree).%%-----------------------------------------------------------------%% Returns dividing keys, left of or right of a tree.%%-----------------------------------------------------------------bplus_get_lkey(Tree, Pos) -> element(Pos*2-1, Tree).bplus_get_rkey(Tree, Pos) -> element(Pos*2+1, Tree).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?