文章目录
二叉搜索树
什么是二叉搜索树
二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值。
- 非空右子树的所有的键值大于其根结点的键值。
- 左右子树都是二叉搜索树。
二叉搜索树例子:
二叉搜索树的一些操作
-
Position Find(ElementType X,BinTree BST)
:从二叉搜索树BST中查找元素X,返回其所在结点的地址;-
递归实现
Position Find(ElementType X,BinTree BST) { //查找失败 if(!BST) { return NULL } //在右子树中继续查找 if(X>BST->Data) { return Find(X,BST->Right); } 在左子树中继续查找 else if(X<BST->Data) { return Find(X,BST->Left); } //找到后返回地址 else { return BST; } }
-
非递归实现:由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数。
Position Find(ElementType X,BinTree BST) { while(BST) { if(X>BST->Data) { BST=BST->Right;//向右子树移动,继续查找 } else if(X<BST->Data) { BST=BST->Left;//向左子树移动,继续查找 } else { return BST;//查找成功,返回地址 } } return NULL;//查找失败 }
查找的效率决定于树的高度。
-
-
Position FindMin(BinTree BST)
:从二叉搜索树BST中查找并返回最小元素所在结点的地址;
根据二叉搜索树的特点可知,最小元素一定在树的最左分枝的端结点上-
递归实现
Position FindMin(BinTree BST) { //如果是空树,返回NULL if(!BST) { return BST; } //如果不是空树,且左子树不为空,向左走 else if(BST->Left) { return FindMin(BST->Left); } //如果不是空树,且左子树为空,此结点就是所求元素结点,返回地址 else { return BST; } }
-
非递归实现
Position FindMin(BinTree BST) { //如果二叉树是空的,返回NULL,否者找到最左端结点 if(BST) { //一直往左,直到最左的结点 while(BST->Left) { BST=BST->Left; } } return BST; }
-
-
Position FindMax(BinTree BST)
:从二叉搜索树BST中查找并返回最大元素所在结点的地址;
根据二叉搜索树的特点可知,最大元素一定在树的最右分枝的端结点上-
递归实现
Position FindMax(BinTree BST) { //如果是空树,返回NULL if(!BST) { return BST; } //如果不是空树,且右子树不为空,向右走 else if(BST->Left) { return FindMin(BST->Left); } //如果不是空树,且右子树为空,此结点就是所求元素结点,返回地址 else { return BST; } }
-
非递归实现
Position FindMax(BinTree BST) { //如果二叉树是空的,返回NULL,否者找到最右端结点 if(BST) { //一直往右,直到最右的结点 while(BST->Right) { BST=BST->Right; } } return BST; }
-
-
BinTree Insert(ElementType X,BinTree BST)
:将键值为X的结点插入二叉搜索树;BinTree Insert(ElementType X,BinTree BST) { //树是空树,增加一个结点 if(!BST) { BST=(BinTree)malloc(sizeof(struct TreeNode)); BST->Data=X; BST->Left=NULL; BST->Right=NULL; } //不是空树,比较根结点和X的大小。 else { //X比根结点小,往插入左子树 if(X<BST->Data) { BST->Left=Insert(X,BST->Left); } //X比根结点大,往插入右子树 else if(X>BST->Data) { BST->Right=Insert(X,BST->Right); } //else x已经存在,什么都不做 } return BST; }
-
BinTree Delete(ElementType X,BinTree BST)
:将二叉查找树中键值为X的结点删除。
考虑三种情况:- 要删除的是叶结点:直接删除,并再修改其父结点指针,置为NULL
- 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点。
- 要删除的结点有左右两棵子树:用右子树的最小元素或者左子树的最大元素替代被删除结点,然后将右子树的最小元素或者左子树的最大元素删除
这样做的好处:右子树的最小元素或者左子树的最大元素一定只有一个儿子结点。
BinTree Delete(ElementType X,BinTree BST) { Position Tmp; //树里没有要找的元素 if(!BST) { printf("要删除的元素未找到\n"); } //左子树递归删除 else if(X<BST->Data) { BST->Left=Delete(X,BST->Left); } //右子树递归删除 else if(X>BST->Right) { BST->Right=Delete(X,BST->Right); } //找到要删除的结点 else { //要删除的结点有两个孩子结点 if(BST->Left&&BST->Right) { //在右子树中找最小的元素代替删除的结点 Tmp=FindMin(BST->Right); BST->Data=Tmp->Data; //在删除结点的右子树中删除最小元素结点 BST->Right=Delete(BST->Data,BST->Right); } //要删除的结点没有儿子结点或则只有一个儿子结点 else { Tmp=BST; //没有左结点时,其父结点指向该结点的右结点 if(!BST->Left) { BST=BST->Right; } //没有右结点时,其父结点指向该结点的左结点 else if(!BST->Right) { BST=BST->Left; } free(Tmp); } } return BST; }