二叉查找树的生成和常用方法(完整版)
二叉查找树(搜索树)
二叉树的一个重要的应用是他们在查找中的使用。假设给树的每个结点指定一个关键值。
对于树的每个结点X,
二叉查找树的左子树中的所有关键字的值小于X的关键字值。
二叉查找树的右子树中的所有关键字的值大于X的关键字值。
附上代码和相关代码解释
二叉查找树(搜索树)的生成
二叉查找树在生成的初始化的过程中要时刻遵循二叉查找树的两条设计规则,可以通过根结点后不断插入,也可以在初始化的时候创建一颗自己设计好的二叉查找树。
//结构体长度声明
#define LEN_TREE sizeof(struct TreeNode)
//树结构体
typedef struct TreeNode *Bintree;
//typedef Bintree Position;
typedef struct TreeNode {
int data;
Bintree left;
Bintree right;
}TreeNode;
//创建二叉树
void MakeTree(struct TreeNode* root);
//二叉搜索树的查找
Position Find(int x, struct TreeNode* root);
Position FindMin(struct TreeNode* root);
Position FindMax(struct TreeNode* root);
//二叉搜索树的插入
Position Insert(struct TreeNode* P, int x);
//二叉搜索树的删除
void Delete(struct TreeNode* root, int x);
二叉查找树(搜索树)的查找
查找的方式主要是依据二叉查找树的性质,通过根结点的比对向下搜索。代码比较简单,有问题可以留言。
//查找结点
Position Find(int x, struct TreeNode* root) {
struct TreeNode* p;
p = root;
while (p) {
if (p->data > x) {
p = p->left;
}
else if (p->data < x) {
p = p->right;
}
else {
return p;
}
}
return p;
}
二叉查找树(搜索树)搜索最大最小值
最大最小值的搜索相对而言也不是很难懂,就性质可得,最左边的是最小值,而最右边的为最大值。
说一说我之前的一个误区
这棵树上到底绿色的算最右边的结点还是红色的算最右边的结点。
后来还是根据,根结点的右子树中的所有值都大于根结点的值,而左子树中所有的值都小于根结点的值,由此可知,红色小于绿色,搜索最小值只需要从根结点开始,不断查找左子树即可。
//寻找最小结点
Position FindMin(struct TreeNode* root) {
struct TreeNode* p;
p = root;
while (p->left) {
p = p->left;
}
printf("%d is the Minimum number!\n", p->data);
return p;
}
//寻找最大结点
Position FindMax(struct TreeNode* root) {
struct TreeNode* p;
p = root;
while (p->right) {
p = p->right;
}
printf("%d is the Maximum number!\n", p->data);
if (p == NULL) {
printf("This data is not found!\n");
return NULL;
}
else {
return p;
}
}
二叉查找树(搜索树)的插入
二叉树的插入没有太多技巧,略过了。
//结点插入
Position Insert(struct TreeNode* P, int x) {
if (P == NULL) {
P = malloc(LEN_TREE);
P->data = x;
P->left = NULL;
P->right = NULL;
}
else if (P->data > x) {
P->left = Insert(P->left, x);
}
else if (P->data < x) {
P->right = Insert(P->right, x);
}
return P;
}
二叉查找树(搜索树)的删除
二叉查找树的函数就需要更具结点的子树情况灵活的改变删除策略
要删除的结点不存在子树
这种情况只需要通过搜索,找到对应的子树,直接删除即可。
要删除的结点存在一个左子树或者右子树
在删除结点的同时需要将该结点的子树连接到该结点的父亲之下。
要删除的结点同时存在左子树和右子树
这种情况下又两种操作方式:
1.在右子树中寻找最大值插入该结点,再将该最大值的左子树连接到最大值的父亲结点的右边。
2.在左子树中寻找最小值插入该结点,再将该最小值的右子树连接到最小值的父亲子树的左边(不画插入了,有点麻烦。。。大家能懂的吧)。
//结点删除
void Delete(struct TreeNode* root, int x) {
struct TreeNode* p;
struct TreeNode* Rp;
struct TreeNode* Rp2;
p = root;
while (p) {
if (p->data > x) {
Rp = p;
p = p->left;
}
else if (p->data < x) {
Rp = p;
p = p->right;
}
else {
break;
//return p;
}
}
if (p == NULL) {
printf("%d is not exist!\n",x);
}
else if (p->left == NULL&&p->right == NULL) {
if (Rp->left == p) {
Rp->left = NULL;
}
else {
Rp->right = NULL;
}
printf("%d has deleted!\n", p->data);
free(p);
}
else if (p->left != NULL&&p->right == NULL) {
if (Rp->left == p) {
Rp->left = p->left;
}
else {
Rp->right = p->left;
}
printf("%d has deleted!\n", p->data);
free(p);
}
else if (p->left == NULL&&p->right != NULL) {
if (Rp->left == p) {
Rp->left = p->right;
}
else {
Rp->right = p->right;
}
printf("%d has deleted!\n", p->data);
free(p);
}
else if (p->left != NULL&&p->right != NULL) {
Rp = p;
p = p->right;
while (p->left) {
Rp2 = p;
p = p->left;
}
Rp->data = p->data;
if (p->right) {
Rp2->left = p->right;
free(p);
}
else {
Rp2->left = NULL;
free(p);
}
}
}