教程:二叉排序树(BST)
二叉排序树
(也称二叉查找树)或者是一棵空树,或者是具有下列特性的二叉树
1)若左子树非空,则左子树上所有结点的值均小于根结点的值。
2)若右子树非空,则右子树上所有结点的值均大于根结点的值。
3)左、右子树也分别是一棵二叉排序树。
根据二叉排序树的定义,左子树结点值<根结点值<右子树结点值
,所以对二叉排序树进行中序遍历,可以得到一个递增的有序序列。
例如,图5.21所示二叉排序树的中序遍历序列为1 2 3 4 6 8。
二叉排序树可用于元素的有序组织、搜索
二叉排序树的查找是从根结点开始的,沿某个分支逐层向下进行比较的过程。
其查找过程描述如下:若二叉排序树非空,则将给定值与根结点的关键字比较,若相等,则查找成功;若不等,则当根结点的关键字值大于给定关键字值时,在根结点的左子树中查找;否则在根结点的右子树中查找。
实现代码:
//查找的递归算法
BSTNode *Search(BSTNode *root, int x){
if(root->data == x){
return root;
}else if(x < root->data){
return Search(root->left, x);
}else{
return Search(root->right, x);
}
}
//查找的非递归算法
BSTNode *Search(BSTNode *root, int x){
BSTNode *p = root;
while(p!=NULL && p->data!=x){
if(x < p->data)
p = p->left;
else
p = p->right;
}
return p;
}
//插入的递归算法
BSTNode *Insert(BSTNode *root, int x){
if(root == NULL){
root = CreateTreeNode(x);
return root;
}
if(x < root->data){
root->left = Insert(root->left, x);
}
if(x > root->data){
root->right = Insert(root->right, x);
}
return root;
}
//插入的非递归算法
BSTNode *Insert1(BSTNode *root, int x){
BSTNode *parent = NULL;
BSTNode *p = root;
if(root == NULL){
root = CreateTreeNode(x);
return root;
}
while(p != NULL){
parent = p;
if(x < p->data){
p = p->left;
}else{
p = p->right;
}
}
if(parent->data >x){
parent->left = CreateTreeNode(x);
}else{
parent->right = CreateTreeNode(x);
}
return root;
}
构造一棵二叉排序树就是依次输入数据元素,并将它们插入二叉排序树中适当位置上的过程。
构造二叉排序树的过程:每读入一个元素,就建立一个新结点,若二叉排序树为空,则将新结点作为二叉排序树的根结点;若二叉排序树非空,则将新结点的值与根结点的值比较,若小于根结点的值,则插入左子树,否则插入右子树。
void Create(BSTNode *&root, int str[], int n){
root = NULL;
for(int i=0; i<n; i++){
Insert(root, str[i]);
}
}
//删除
bool Delete(BSTNode *p){
//在二叉排序树中删除结点p, 并重新连接它的左右子树
BSTNode *q, *s;
//1.p为叶子结点
if(p->left==NULL && p->right==NULL){
p = NULL;
}
//2.1 p左子树为空, 重接右子树
else if(p->left == NULL){
q = p;
p = p->right;
free(q);
}
//2.2 p右子树为空, 重接左子树
else if(p->right == NULL){
q = p;
p = p->left;
free(q);
}
//3. p左右子树均不为空
else{
q = p;
s = p->right; //找到p的右子树的最左端(中序直接后继)
while(s->left != NULL){
q = s;
s = s->left;
}
p->data = s->data;
if(q != p) //判断是否执行上述while循环
q->left = s->right; //执行上述while循环,重接*q的左子树
else
q->right = s->right; //未执行上述while循环,重接*q的右子树,对于这个情况,可以参考代码后给出的示例图
free(s);
}
return true;
}
bool DeleteBST(BSTNode *root, int x){
if(root == NULL){
return false;
}else{
if(x == root->data)
return Delete(root);
else if(x < root->data)
return DeleteBST(root->left, x);
else
return DeleteBST(root->right, x);
}
}
二叉排序树的结点定义:
typedef struct BSTNode{
int data;
struct BSTNode *left,*right;
}BSTNode;
二叉树结点的创建:
// 二叉树结点的创建
BSTNode *CreateTreeNode(int x){
BSTNode *p=(BSTNode *)malloc(sizeof(BSTNode));
p->data =x;
p->left=NULL;
P->right=NULL;
return p;
}
完整代码及实例
#include
using namespace std;
typedef struct BSTNode{
int data;
struct BSTNode *left;
struct BSTNode *right;
}BSTNode;
#define N 100
//查找的递归算法
BSTNode *Search(BSTNode *root, int x){
if(root->data == x){
return root;
}else if(x < root->data){
return Search(root->left, x);
}else{
return Search(root->right, x);
}
}
//查找的非递归算法
BSTNode *Search1(BSTNode *root, int x){
BSTNode *p = root;
while(p!=NULL && p->data!=x){
if(x < p->data)
p = p->left;
else
p = p->right;
}
return p;
}
//二叉树结点创建
BSTNode *CreateTreeNode(int x){
BSTNode *p = (BSTNode *)malloc(sizeof(BSTNode));
p->data = x;
p->left = NULL;
p->right = NULL;
return p;
}
//插入的递归算法
BSTNode *Insert(BSTNode *root, int x){
if(root == NULL){
root = CreateTreeNode(x);
return root;
}
if(x < root->data){
root->left = Insert(root->left, x);
}
if(x > root->data){
root->right = Insert(root->right, x);
}
return root;
}
//插入的非递归算法
BSTNode *Insert1(BSTNode *root, int x){
BSTNode *parent = NULL; //记录当前结点的父结点
BSTNode *p = root;
if(root == NULL){
root = CreateTreeNode(x);
return root;
}
while(p != NULL){
parent = p;
if(x < p->data){
p = p->left;
}else{
p = p->right;
}
}
if(parent->data >x){
parent->left = CreateTreeNode(x);
}else if(parent->data < x){
parent->right = CreateTreeNode(x);
}
return root;
}
//构建
void Create(BSTNode *&root, int str[], int n){
root = NULL;
for(int i=0; i<n; i++){
root = Insert(root, str[i]);
}
}
//删除
bool Delete(BSTNode *p){
//在二叉排序树中删除结点p, 并重新连接它的左右子树
BSTNode *q, *s;
//1.p为叶子结点
if(p->left==NULL && p->right==NULL){
p = NULL;
}
//2.1 p左子树为空, 重接右子树
else if(p->left == NULL){
q = p;
p = p->right;
free(q);
}
//2.2 p右子树为空, 重接左子树
else if(p->right == NULL){
q = p;
p = p->left;
free(q);
}
//3. p左右子树均不为空
else{
q = p;
s = p->right; //找到p的右子树的最左端(中序直接后继)
while(s->left != NULL){
q = s;
s = s->left;
}
p->data = s->data;
if(q != p) //判断是否执行上述while循环
q->left = s->right; //执行上述while循环,重接*q的左子树
else
q->right = s->right; //未执行上述while循环,重接*q的右子树
free(s);
}
return true;
}
bool DeleteBST(BSTNode *root, int x){
if(root == NULL){
return false;
}else{
if(x == root->data)
return Delete(root);
else if(x < root->data)
return DeleteBST(root->left, x);
else
return DeleteBST(root->right, x);
}
}
void LevelOrder(BSTNode *root){
queue<BSTNode *> treenode; //队列存储结点
if(root != NULL)
treenode.push(root); //根结点入队
while(!treenode.empty()){
BSTNode *p = treenode.front();
treenode.pop(); //根结点出队
cout<<p->data<<" "; //输出队首元素,即当前访问的结点值
if(p->left != NULL){
treenode.push(p->left);//如果有左子树,则将左子树的根结点入队
}
if(p->right != NULL){
treenode.push(p->right);//如果有右子树,则将右子树的根结点入队
}
}
}
int main(){
BSTNode *root;
int n;
cin>>n;
int str[n];
for(int i=0; i<n; i++){
cin>>str[i];
}
Create(root,str,n);
cout<<"当前二叉排序树的层序遍历序列为:";
LevelOrder(root);
cout<<endl;
BSTNode *p = Search(root, 17);
cout<<"结点17的右孩子结点值为:"<<p->right->data<<endl;
DeleteBST(root, 78);
cout<<"删除结点78后的二叉排序树的层序遍历序列为:";
LevelOrder(root);
return 0;
}
教程:平衡二叉树(AVL树)
练习:
练习:
教程:哈夫曼树和哈夫曼编码