对平衡二叉搜索树Balance Binary Search Tree所有功能的实现的头文件

最近在学计算几何,经常要用到BBST去储存一些数据,正是因为BBST查找效率极高O(logn)并且占用的空间仍是线性的,而其构造的时间需要O(nlogn),是可以接受的。所以在这里总结了BBST插入、删除、查找的功能到一个头文件中:

具体实现的原理可见https://blog.csdn.net/derbi123123/article/details/104204220

头文件:

#include <math.h>
#include <iostream>
using namespace std;
#define ElementType int//这里只需要改变ElementType的类型,下面的数据类型都是ElementType

typedef struct node *AVL;
struct node{
	ElementType data;
	int height;//节点高度(根节点最高,叶子结点最低)
	AVL left;
	AVL right;
};
//创建平衡二叉树:
AVL BuildBBST(ElementType data)
{
	AVL Root=new node;
	Root->data=data;
	Root->height=1;
	Root->left=NULL;
	Root->right=NULL;
	return Root;
}
//获得节点的高度:
int GetHeight(AVL tree)
{
	if(!tree) return 0;
	return tree->height;
}
//得到节点的平衡因子:
int GetBT(AVL tree)
{
	int BT=GetHeight(tree->left)-GetHeight(tree->right);//不用绝对值是因为方便判断用哪种方式调整
	return BT;
}
//右单旋:
AVL RR(AVL A)
{
	AVL B=A->right;
	A->right=B->left;
	B->left=A;
	//更新节点高度:
	A->height=max(GetHeight(A->left),GetHeight(A->right))+1;
	B->height=max(GetHeight(B->right),A->height)+1;
	return B;
}
//左单旋:
AVL LL(AVL A)
{
	AVL B=A->left;
	A->left=B->right;
	B->right=A;
	//更新节点高度:
	A->height=max(GetHeight(A->left),GetHeight(A->right))+1;
	B->height=max(GetHeight(B->left),A->height)+1;
	return B;
}
//左—右双旋:
AVL LR(AVL A)
{
	A->left=RR(A->left);//旋转B、C、CR/CL
	return LL(A);//旋转A、C、CR/CL
}
//右—左单旋:
AVL RL(AVL A)
{
	A->right=LL(A->right);//旋转B、C、CR/CL
	return RR(A);//旋转A、C、CR/CL
}
//插入新节点
AVL Insert(AVL tree,ElementType X)
{
	if(!tree){
		tree=new node;
		tree->data=X;
		tree->left=tree->right=NULL;
	}else if(X<tree->data){
		tree->left=Insert(tree->left,X);
		if(GetBT(tree)==2){//平衡因子超过1,自己想为什么是==2而不是>=2
			if(tree->left->data>X){//左单旋
				tree=LL(tree);
			}else{//左右单旋
				tree=LR(tree);
			}
		}
	}else{
		tree->right=Insert(tree->right,X);
		if(GetBT(tree)==-2){//平衡因子超过1,自己想为什么是==-2而不是<=-2
			if(tree->right->data<X){//右单旋
				tree=RR(tree);
			}else{//右左单旋
				tree=RL(tree);
			}
		}
	}
	tree->height=max(GetHeight(tree->left),GetHeight(tree->right))+1;
	return tree;
}
//删除节点
AVL Delete(ElementType X, AVL T) { //递归删除,返回根结点
    if(T == NULL) {
        printf("find null\n");
    } else if (X < T->data) {
        T->left = Delete(X, T->left); //递归删除左子树,返回根结点(当前结点的右子树结点高度比较大)
        if(GetBT(T)== 2) {
            AVL p = T->right;
            if(GetHeight(p->left) > GetHeight(p->right)) { //当前结点的右子树结点的左子树结点高度比较大,对右边的结点双旋
                T = RR(T);
            } else { //当前结点的右子树结点的右子树结点高度比较大,对右边的结点单旋
                T = RR(T);
            }
        }
    } else if (X > T->data) { //递归删除右子树,返回根结点(当前结点的左子树结点高度比较大)
        T->right = Delete(X, T->right);
        if(GetBT(T)== -2) {
            AVL p = T->left;
            if(GetHeight(p->left) < GetHeight(p->right)) { //当前结点的左子树结点的右子树结点高度比较大,对左边的结点双旋
                T = LR(T);
            } else { //当前结点的左子树结点的左子树结点高度比较大,对左边的结点单旋
                T = LL(T);
            }
        }
    } else {
        if(T->left != NULL && T->right != NULL) { //待删除的结点有两个孩子结点
            if(GetHeight(T->left) > GetHeight(T->right)) { //当前结点的左子树结点高度比较大
                AVL p = T->left;
                while(p->right != NULL) { //寻找当前结点的前驱结点,用于删除
                    p = p->right;
                }
                T->data = p->data;
                T->left = Delete(p->data, T->left);
            } else { //当前结点的右子树结点高度比较大
                AVL p = T->right;
                while(p->left != NULL) { //寻找当前结点的后继结点,用于删除
                    p = p->left;
                }
                T->data = p->data;
                T->right = Delete(p->data, T->right);
            }
        } else if(T->left == NULL && T->right == NULL){ //待删除的结点无孩子结点
            T = NULL;
        } else if(T->right == NULL) { //待删除的结点只有左孩子结点
            AVL p = T;
            T = T->left;
            free(p);
        } else { //待删除的结点只有右孩子结点
            AVL p = T;
            T = T->right;
            free(p);            
        }
    }

    if(T != NULL) {
        T->height = max(GetHeight(T->left), GetHeight(T->right)) + 1; //更新根结点高度,左右子节点高度的最大值加1
    }
    return T;
}

//遍历BBST(其实也只能前中后序遍历选一种,我看前序遍历还比较正常一些)
void TaveralBBST(AVL tree)
{
	if(tree){
		cout<<tree->data<<" ";
		TaveralBBST(tree->left);
		TaveralBBST(tree->right);
	}
}

//查找元素:如果存在那就返回对应节点,不存在返回小于查找元素的最大值
AVL Find(ElementType X,AVL T)
{
	if(T->data==X){
		return T;
	}else if(T->data<X){
		Find(X,T->right);
	}else if(T->data>X){
		Find(X,T->left);
	}else{
		return NULL;
	}
}

测试用的程序:

#include <conio.h>
#include "BBST.h"
#include <iostream>
#define NUM 10
using namespace std;

int main()
{
	//先创建只有根节点的BBST
	AVL root;
	ElementType data;
	cin>>data;
	root=BuildBBST(data);
	//向BBST中加入元素
	node bbst[NUM];
	for(int i=0;i<NUM;i++){
		cin>>bbst[i].data;
		root=Insert(root,bbst[i].data);
	}
	//输出BBST的高度
	cout<<root->height<<endl;
	//前序遍历输出所有节点
	TaveralBBST(root);
	cout<<"\n";
	//删除根节点
	root=Delete(root->data,root);
	//输出新的根节点,前序遍历输出所有节点
	cout<<root->data<<endl;
	TaveralBBST(root);
	//查找节点
	ElementType searchData;
	cin>>searchData;
	AVL child=Find(searchData,root);
	if(!child)
		cout<<"找不到您要找的节点"<<endl;
	else
		cout<<child->data;
	getch();
	return 0;
}

实例:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 二叉搜索树Binary Search Tree):是一棵空树或者具有下列性质的二叉树:若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;它的左右子树也分别为二叉搜索树。 中序遍历序列:对于任意一棵二叉树,中序遍历的结果都是一个序列,这个序列称为中序遍历序列。 因此,判断一棵二叉树是否为二叉搜索树,可以先进行中序遍历,再判断遍历结果是否为升序序列。 以下是 Python 代码实现: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def inorderTraversal(root: TreeNode) -> List[int]: res = [] if not root: return res res.extend(inorderTraversal(root.left)) res.append(root.val) res.extend(inorderTraversal(root.right)) return res def isBST(root: TreeNode) -> bool: res = inorderTraversal(root) for i in range(1, len(res)): if res[i] <= res[i-1]: return False return True ``` 其中,`TreeNode` 是二叉树的节点类,`inorderTraversal` 函数是实现二叉树中序遍历的递归函数,`isBST` 函数是判断二叉树是否为二叉搜索树的函数。 ### 回答2: 要实现这个函数,首先我们可以使用递归的方式对二叉树进行中序遍历,即先遍历左子树,再访问根节点,最后遍历右子树。遍历过程中将遍历到的节点值保存到一个数组中。 接下来,我们需要判断该数组是否是按升序排列的,即判断是否是一棵二叉搜索树。我们可以遍历数组,依次比较相邻的节点值,如果前一个节点的值大于等于后一个节点的值,则认为不是二叉搜索树。反之,如果整个数组都符合这个条件,则认为是一个二叉搜索树。 以下是一个简单的实现代码: ``` class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def inorderTraversal(root): if not root: return [] result = [] inorder(root, result) return result def inorder(root, result): if not root: return inorder(root.left, result) result.append(root.val) inorder(root.right, result) def isBST(root): inorder_result = inorderTraversal(root) for i in range(1, len(inorder_result)): if inorder_result[i] <= inorder_result[i-1]: return False return True ``` 这个函数的时间复杂度是O(n),其中n是二叉树中节点的数量,因为我们需要遍历每个节点并将节点的值保存到数组中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值