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 + -
显示快捷键?