造价通

反馈
取消

热门搜词

造价通

取消 发送 反馈意见

BST排序树

2022/07/16170 作者:佚名
导读:二叉排序树(Binary Sort Tree:BST) 1、二叉排序树的定义 二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树: ①若它的左子树非空,则左子树上所有结点的值均小于根结点的值; ②若它的右子树非空,则右子树上所有结点的值均大于根结点的值; ③左、右子树本身又各是一棵

二叉排序树(Binary Sort Tree:BST)

1、二叉排序树的定义

二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:

①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;

②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;

③左、右子树本身又各是一棵二叉排序树。

上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。

2、二叉排序树的特点

由BST性质可得:

(1) 二叉排序树中任一结点x,其左(右)子树中任一结点y(若存在)的关键字必小(大)于x的关键字。

(2) 二叉排序树中,各结点关键字是惟一的。

注意:

实际应用中,不能保证被查找的数据集中各元素的关键字互不相同,所以可将二叉排序树定义中BST性质(1)里的"小于"改为"小于等于",或将BST性质(2)里的"大于"改为"大于等于",甚至可同时修改这两个性质。

(3) 按中序遍历该树所得到的中序序列是一个递增有序序列。

【例】下图所示的两棵树均是二叉排序树,它们的中序序列均为有序序列:2,3,4,5,7,8。

3、二叉排序树的存储结构

typedef int KeyType; //假定关键字类型为整数

typedef struct node { //结点类型

KeyType key; //关键字项

InfoType otherinfo; //其它数据域,InfoType视应用情况而定,下面不处理它

struct node *lchild,*rchild,*parent; //左右孩子指针

} BSTNode;

typedef BSTNode *BSTree; //BSTree是二叉排序树的类型

二叉排序树的基本操作(pascal):

1.中序遍历所有元素

procedure tree_walk(x:longint);

begin

if x<>0 then

begin

tree_walk(left[x]);

write(key[x]);

tree_walk(right[x]);

end;

2.查找给定的元素

function tree_search(x,k:longint):longint;

begin

if (x=0) or (k=key[x]) then exit(x);

if k

end;

非递归版本

function tree_search(x,k:longint):longint;

begin

while (x<>0) and (k<>key[x]) do

begin

if k

end;

exit(x);

end;

3.查找最小元素

function tree_minimum(x:longint):longint;

begin

while left[x]<>0 do

x:=left[x];

exit(x);

end;

查找最大元素

function tree_maximum(x:longint):longint;

begin

while right[x]<>0 do

x:=right[x];

exit(x);

end;

4. 求后继

function tree_successor(x:longint):longint;

var

y:longint;

begin

if right[x]<>0 then exit(tree_minimum(right[x]));//若右子树不空,则返回右子树中的最小值

y:=p[x];//若右子树为空,则后继y为x的最低祖先节点,且y的左儿子也是x的祖先

while (y<>0) and (x=right[y]) do

begin

x:=y;

y:=p[y];

end;

exit(y);//注意,若y为0,则x无后继

end;

//注意,函数返回值为节点编号,并不是节点本身的值

5.插入

procedure tree_insert(z:longint);//注意z为节点编号,并非树中的值

var

x,y:longint;

begin

y:=0;

x:=root;

while x<>0 do//查找z的父节点,y记录

begin

y:=x;

if key[z]

end;

p[x]:=y;

if y=0 then root:=z//若z为根节点

else begin

if key[z]

end;

end;

6.删除

删除操作是最麻烦的,分3种情况:

(1)若z无子树,则就删除z节点,更新p[z]的值为空

(2)若z有一个子树,删除z节点,更新p[z]的值为z的儿子节点,更新left[p[z]] 或 right[p[z]]

(3)若z有两棵子树,先找到z的后继y(后继节点无左子树,可证),删除y节点,更新p[y]与left[p[y]] 或 right[p[y]],最后用节点y的数据覆盖z节点

procedure tree_delete(z:longint);

var

x,y:longint;

begin

if (left[z]=0) or (right[z]=0) then y:=z

else y:=tree_successor(z);

if left[y]<>0 then x:=left[y]

else x:=right[y];

if x<>0 then p[x]:=p[y];

if p[y]=0 then root:=x

else begin

if y=left[p[y]] then left[p[y]]:=x

else right[p[y]]:=x;

end;

if z<>y then key[z]:=key[y];

end;

7.查找数中第k大元素

需要对每个节点新开一个域v[x],记录该节点的有多少子节点,

查找时分三种情况:

(1)k=v[left[x]] 1 则当前x节点为所求

(2)k<=v[left[x]] 则在左子树中继续查找

(3)k>v[left[x]] 1 则在右子树中继续查找,k更新为k-left[x]-1;

function find(x,k:longint):longint;

begin

if v[left[x]] 1=k then exit(key[k])

else if v[left[x]]>=k then exit(find(left[x],k))

else exit(find(right[x],k-v[left[x]]-1));

end;

*文章为作者独立观点,不代表造价通立场,除来源是“造价通”外。
关注微信公众号造价通(zjtcn_Largedata),获取建设行业第一手资讯

热门推荐

相关阅读