首页 > 代码库 > 二叉查找树
二叉查找树
一棵树是N个节点和N-1条边的集合。因为,每条边都将某个节点连接到它的父亲,而除去根节点外每一个节点都有一个父亲。
使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值。
在程序中,一定要记得处理的根节点为空的情况。除了删除节点的操作外,其它操作都比较容易实现,通常是递归地编写这些操作例程。删除节点的规则如下:
- 如果节点是树叶,立即删除它。
- 如果节点有一个儿子,那么将该节点的父节点调整为指向该儿子,然后删除该节点。
- 如果节点有两个儿子,那么查找该节点右子树中的最小数据,用最小数据替换该节点的数据,然后删除拥有最小数据的那个节点。因为右子树中最小数据的节点必定不会有做孩子,所以又回到了情况1或情况2.
例程:
#include <stdio.h>
typedef
int
ElementType;
typedef
struct
TreeNode *Position;
typedef
struct
TreeNode *SearchTree;
struct
TreeNode
{
// 自身数据加上指向左右子树的指针
ElementType Element;
SearchTree Left;
SearchTree Right;
};
SearchTree MakeEmpty(SearchTree T)
{
if
(T != NULL)
{
MakeEmpty(T->Left);
MakeEmpty(T->Right);
free
(T);
}
return
T;
}
// 返回包含查找元素的指针或NULL
Position Find(SearchTree T, ElementType x)
{
if
(T == NULL)
return
NULL;
else
if
(T->Element < x)
return
Find(T->Right, x);
else
if
(T->Element > x)
return
Find(T->Left, x);
else
return
T;
}
Position FindMin(SearchTree T)
{
// 这个判断是必须的
if
(T != NULL)
while
(T->Left)
T = T->Left;
return
T;
}
// 递归版本
Position FindMin_recurse(SearchTree T)
{
if
(T == NULL)
return
NULL;
else
if
(T->Left == NULL)
return
T;
else
return
FindMin(T->Left);
}
Position FindMax(SearchTree T)
{
// 这个判断是必须的
if
(T != NULL)
while
(T->Right)
T = T->Right;
return
T;
}
// 相同节点已在树中,则不做任何操作
// 返回指向新树根的指针
SearchTree Insert(SearchTree T, ElementType x)
{
if
(T == NULL)
{
T =
malloc
(
sizeof
(
struct
TreeNode));
if
(T == NULL)
return
NULL;
T->Element = x;
T->Left = T->Right = NULL;
}
else
if
(x < T->Element)
T->Left = Insert(T->Left, x);
else
if
(x > T->Element)
T->Right = Insert(T->Right, x);
return
T;
}
SearchTree Delete(SearchTree T, ElementType x)
{
Position tmp;
if
(T == NULL)
return
NULL;
if
(x < T->Element)
T->Left = Delete(T->Left, x);
else
if
(x > T->Element)
T->Right = Delete(T->Right, x);
else
// 找到要删除的节点
{
if
(T->Left && T->Right)
// 该节点有两个儿子
{
tmp = FindMin(T->Right);
T->Element = tmp->Element;
T->Right = Delete(T->Right, tmp->Element);
}
else
// 有一个儿子或没有儿子
{
tmp = T;
if
(T->Left == NULL)
T = T->Right;
else
if
(T->Right == NULL)
T = T->Left;
free
(tmp);
}
}
return
T;
}
SearchTree CreateTree()
{
// 一定要初始化指针,因为Insert函数根据指针是否为空进行插入
SearchTree t = NULL;
return
t;
}
int
main()
{
SearchTree tree = CreateTree();
int
i;
for
(i = 0; i < 10; i++)
tree = Insert(tree, i);
printf
(
"Max = %d\n"
, FindMin(tree)->Element);
printf
(
"Max = %d\n"
, FindMax(tree)->Element);
return
0;
}
普通的二叉查找树期望的任意操作的平均时间为O(logN),而由于在删除的时候,我们总是用右子树的最小节点代替被删除节点,导致左子树比右子树深度更深。
参考:
《数据结构于算法分析》 P70、P73.
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。