bst
1、什么是二叉排序树
二叉搜索树(BST,binary Search Tree),也称二叉排序树或二叉查找树
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值。
- 非空右子树的所有键值大于其根结点的键值。
- 左、右子树都是二叉搜索树。
2、二叉搜索树的查找操作
-
查找从根结点开始,如果树为空,返回NULL
-
若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:
- 若X小于根结点键值,只需在左子树中继续搜索;
- 如果X大于根结点的键值,在右子树中进行继续搜索;
- 若两者比较结果是相等,搜索完成,返回指向此结点的指针。
递归实现
BiTree SearchBST(BiTree &tree, ElemType key)
{
if (tree == NULL)
return NULL;
if (key > tree->data)
SearchBST(tree->rchild,key);
else if (key < tree->data)
SearchBST(tree->lchild, key);
else
return tree;
}
非递归实现
BiTree BST_search(BiTree root, ElemType x)
{
BiTree p = root;
while (p!= NULL)
{
if (x < p->data)
p = p->lchild;
else if (x > p->data)
p = p->rchild;
else
return p;
}
return NULL;
}
3、查找最大和最小元素
最大元素一定是在树的最右分枝的端结点上
最小元素一定是在树的最左分枝的端结点上
//递归寻找最大值
BiTree findmax(BiTree pRoot)
{
BiTree p = pRoot;
if (p == NULL)
return NULL;
else
{
if (p->rchild != NULL)
findmax(p->rchild);
else
return p;
}
}
//非递归寻找最小值
BiTree findmin(BiTree pRoot)
{
BiTree p = pRoot;
if (p == NULL)
return NULL;
while (p->lchild != NULL)
p=p->lchild;
return p;
}
4、二叉搜索树的插入
关键是要找到元素应该插入的位置,可以采用与Find类似的方法
//在树中插入一个节点
BiTree Insert(BiTree pRoot,ElemType key)
{
if (pRoot == NULL)
{
pRoot = (BiTree)malloc(sizeof(BiTNode));
pRoot->data = key;
pRoot->lchild = NULL;
pRoot->rchild = NULL;
}
else if (key < pRoot->data)
pRoot->lchild = Insert(pRoot->lchild, key);
else if (key>pRoot->data)
pRoot->rchild = Insert(pRoot->rchild, key);
else
cout << "节点已经存在" << endl;
return pRoot; //每一步递归调用都要返回,以维持原树结构的不变
}
5、二叉搜索树的删除
考虑三种情况:
-
要删除的结点的左孩子为空:右孩子代替当前结点
-
要删除的结点的右孩子为空:左孩子代替当前结点
-
要删除的结点有左、右两棵子树: 用另一结点替代被删除结点:右子树的最小元素 或者 左子树的最大元素
//删除树中指定元素key
void DeleteNode(BiTree &tree, ElemType key) //使用引用
{
if (tree == NULL)
return;
if (key > tree->data)
DeleteNode(tree->rchild, key);
else if (key < tree->data)
DeleteNode(tree->lchild,key);
else
{
if (tree->lchild == NULL) //左子树为空,只需要重接右子树
{
BiTree tmp = tree;
tree = tree->rchild;
free(tmp);
}
else if (tree->rchild==NULL) //右子树为空,只需要重接左子树
{
BiTree tmp = tree;
tree = tree->rchild;//此处写错了,应为tmp = tmp->lchild;
free(tmp);
}
else
{
BiTree tmp1, tmp; //tmp为被删除节点,tmp1为tmp前驱
tmp1 = tree;
tmp = tree->lchild;
while (tmp->rchild!=NULL) //左转,向右指,直到尽头
{
tmp1 = tmp;
tmp = tmp->rchild;
}
tree->data = tmp->data;
if (tmp1 != tree)
tmp1->rchild=tmp->lchild; //tmp左子树接到前驱右子树上
else
tmp1->lchild = tmp->lchild; //tmp左子树接到前驱左子树上
free(tmp);
}
}
}
上面代码有一个错误。二叉搜索树删除节点中,当要删除节点只有右孩子时,应重接右子树,代码改为:
else if (tree->rchild==NULL)//右子树为空,只需要重接左子树
{
BiTree tmp = tree;
tmp = tmp->lchild;
free(tmp);
}
c++完整代码
#include<iOStream>
using namespace std;
#define len 15 //定义一个长度
typedef int ElemType;
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode,*BiTree;
//向下遍历,找到节点s应该插入的位置,节点有重复时,忽略这个节点
void SearchTreeNode(BiTree &root, BiTree &s) //注意:使用引用传递
{
if (root == NULL)
return;
if (s->data > root->data)
{
if (root->rchild == NULL){
root->rchild = s;
return;
}
SearchTreeNode(root->rchild, s);//s值大于根节点值,未到达叶子节点,继续向右孩子遍历
}
else if (s->data < root->data)
{
if (root->lchild == NULL){
root->lchild = s;
return;
}
SearchTreeNode(root->lchild, s);//s值小于根节点值,未到达叶子节点,继续向左孩子遍历
}
}
//插入一个节点,树为空,插入节点即为根节点,否则找合适的位置插入
void InsertNode(BiTree &tree, BiTree &s) //注意:使用引用传递
{
if (tree == NULL)
tree = s;
else
SearchTreeNode(tree,s);
}
//二叉排序树创建,每次增加一个结点,插到现有的二叉树上去
void CreateorderBinaryTree(BiTree &tree,int *a)
{
for (int i = 0; i < len; i++)
{
BiTree s = (BiTree)malloc(sizeof(BiTNode));
s->data = a[i];
s->lchild = NULL;
s->rchild = NULL;
InsertNode(tree,s);
}
}
//在树中插入一个节点
BiTree Insert(BiTree pRoot,ElemType key)
{
if (pRoot == NULL)
{
pRoot = (BiTree)malloc(sizeof(BiTNode));
pRoot->data = key;
pRoot->lchild = NULL;
pRoot->rchild = NULL;
}
else if (key < pRoot->data)
pRoot->lchild = Insert(pRoot->lchild, key);
else if (key>pRoot->data)
pRoot->rchild = Insert(pRoot->rchild, key);
else
cout << "节点已经存在" << endl;
return pRoot; //每一步递归调用都要返回,以维持原树结构的不变
}
//删除树中指定元素key
void DeleteNode(BiTree &tree, ElemType key) //使用引用
{
if (tree == NULL)
return;
if (key > tree->data)
DeleteNode(tree->rchild, key);
else if (key < tree->data)
DeleteNode(tree->lchild,key);
else
{
if (tree->lchild == NULL) //左子树为空,只需要重接右子树
{
BiTree tmp = tree;
tree = tree->rchild;
free(tmp);
}
else if (tree->rchild==NULL) //右子树为空,只需要重接左子树
{
BiTree tmp = tree;
tree = tree->rchild;//此处写错了,应为tmp = tmp->lchild;
free(tmp);
}
else
{
BiTree tmp1, tmp; //tmp为被删除节点,tmp1为tmp前驱
tmp1 = tree;
tmp = tree->lchild;
while (tmp->rchild!=NULL) //左转,向右指,直到尽头
{
tmp1 = tmp;
tmp = tmp->rchild;
}
tree->data = tmp->data;
if (tmp1 != tree)
tmp1->rchild=tmp->lchild; //tmp左子树接到前驱右子树上
else
tmp1->lchild = tmp->lchild; //tmp左子树接到前驱左子树上
free(tmp);
}
}
}
//中序遍历
void midOrderTraverse(BiTree tree)
{
if (tree == NULL)
return;
midOrderTraverse(tree->lchild);
cout << tree->data<<" ";
midOrderTraverse(tree->rchild);
}
//查找元素x所在的节点
BiTree SearchBST(BiTree &tree, ElemType key)
{
if (tree == NULL)
return NULL;
if (key > tree->data)
SearchBST(tree->rchild,key);
else if (key < tree->data)
SearchBST(tree->lchild, key);
else
return tree;
}
//非递归查找元素x所在的节点
BiTree BST_search(BiTree root, ElemType x)
{
BiTree p = root;
while (p!= NULL)
{
if (x < p->data)
p = p->lchild;
else if (x > p->data)
p = p->rchild;
else
return p;
}
return NULL;
}
//递归寻找最大值
BiTree findmax(BiTree pRoot)
{
BiTree p = pRoot;
if (p == NULL)
return NULL;
else
{
if (p->rchild != NULL)
findmax(p->rchild);
else
return p;
}
}
//非递归寻找最小值
BiTree findmin(BiTree pRoot)
{
BiTree p = pRoot;
if (p == NULL)
return NULL;
while (p->lchild != NULL)
p=p->lchild;
return p;
}
int main()
{
int a[len] = { 62, 88, 58, 47, 35, 73, 51, 99, 37, 93, 23, 27, 45, 21, 12};
BiTree tree = NULL;
//创建一个二叉树,并中序遍历
CreateOrderBinaryTree(tree,a);
midOrderTraverse(tree);
cout << endl;
//删除一个节点,中序遍历
DeleteNode(tree, 47);
midOrderTraverse(tree);
cout << endl;
//添加一个节点,并中序遍历
Insert(tree, 100);
midOrderTraverse(tree);
cout << endl;
//查找节点
BiTree snode=SearchBST(tree, 23);
if (snode == NULL)
cout <<"查找的节点不存在" <<endl;
else
{
if (snode->lchild == NULL && snode->rchild == NULL)
cout << "节点" <<snode->data<<"叶子节点"<< endl;
else if (snode->lchild != NULL && snode->rchild == NULL)
cout << "节点" << snode->data<<"的左节点是"<<snode->lchild->data << endl;
else if (snode->lchild == NULL && snode->rchild != NULL)
cout << "节点" << snode->data << "的左节点是" << snode->rchild->data << endl;
else
cout << "节点" << snode->data << "的左节点是" << snode->lchild->data
<<" ,右节点是"<<snode->rchild->data<< endl;
}
snode=BST_search(tree, 23);
if (snode != NULL)
cout << snode->data << endl;
else
cout << "查找节点不存在" << endl;
snode = findmax(tree);
if (snode != NULL)
cout <<"最大值为" <<snode->data << endl;
else
cout << "树为空" << endl;
snode = findmin(tree);
if (snode != NULL)
cout << "最小值为" << snode->data << endl;
else
cout << "树为空" << endl;
return 0;
}
运行结果:
参考博文:https://www.cnblogs.com/zhangming-blog/p/5391622.html
相关阅读
(2011-10-18 16:57:43) 转载▼标签: mysql 数据库 2147483647 杂谈 分类:php基础 在用Excel导入数据的时候,碰到11位的数字都变成2
string数组的定义有三种写法: String[] arr = new String[10]; //创建一个长度为10的String 类型数组。 String arr[] = new St
使用SSMS数据库管理工具删除索引 使用表设计器删除索引 表设计器可以删除任何类型的索引,本示例演示删除XML辅助索引,删除其他索
转载:http://blog.51cto.com/wutengfei/1923446 1、首先进入系统创建一个用户 [root@localhost /]# useradd haha #创建用户
这里开始介绍第一种复杂排序算法——希尔排序。我们知道插入排序在有些时候即数据本身基本有序(较小的数据基本在前面,较大的数据基