BST树与AVL树
文章目录
一、二分查找
适用于有序数组
int binary_search(int arr[],int length,int target)
{
int L=0,R=length-1;
while(L<=R)
{
int mid=L+(R-L)/2;
if(arr[mid]<target)
L=mid+1;
else if(arr[mid]>target)
R=mid-1;
else
return mid;
}
return -1;
}
二、二叉搜索树(BST树)
1、简介
BST为二叉树
左子数所有节点都小于根节点,右子树所有节点大于根节点
每个节点的左右子树也是BST
可以在O(logN)时间复杂度内查找一个数是否存在
struct treeNode
{
int data;
treeNode* leftSon;
treeNode* rightSon;
};
2、插入
创建新节点
treeNode* createTreeNode(int value)
{
treeNode* node=new treeNode;
node->data=value;
node->leftSon=NULL;
node->rightSon=NULL;
return node;
}
插入新节点
treeNode* insertNode(treeNode* root,int value)
{
if(root==NULL)
return createTreeNode(value);
if(value<root->data)
root->leftSon=insertNode(root->leftSon,value);
root->rightSon=insertNode(root->rightSon,value);
return root;
}
操作隐患:若插入连续升序或降序节点,容易退化为线性表,复杂度为O(N)
3、查找
treeNode* searchNode(treeNode* root,int target)
{
if(root==NULL||root->data==target)
return root;
if(target<root->data)
return searchNode(root->leftSon,target);
return searchNode(root->rightSon,target);
}
4、删除
获取BST中最小值
treeNode* getMinNode(treeNode* root)
{
if(root==NULL)
return NULL;
while(root->leftSon)
{
root=root->leftSon;
}
return root;
}
删除节点
treeNode* deleteNode(treeNode* root,int target)
{
if(root==NULL)
return root;
if(target<root->data)
root->leftSon=deleteNode(root->leftSon,target);
else if(target>root->data)
root->rightSon=deleteNode(root->rightSon,target);
//开始执行删除操作
else
{
//只有一个子节点或无子节点
if(root->leftSon==NULL)
{
treeNode* temp=root->rightSon;
delete root;
return temp;
}
else if(root->rightSon==NULL)
{
treeNode* temp=root->leftSon;
delete root;
return temp;
}
//有两个子节点
treeNode* temp=getMinNode(root->rightSon); //查找右子数最小值
root->data=temp->data;
root->rightSon=deleteNode(root->rightSon,temp->data);
}
return root;
}
三、平衡二叉树(AVL树)
1、简介
AVL树是一颗自平衡的二叉树
每个节点都有一个平衡因子 p = Height(leftSon) - Height(RightSon)
若每个节点的平衡因子的绝对值均<=1,该树是AVL树
struct treeNode
{
int data;
int height;
treeNode* leftSon;
treeNode* rightSon;
};
2、AVL树的调整
首先在叶节点插入数据
若插入导致不平衡,需对以插入路径上离插入节点最近的平衡因子绝对值大于1的节点为根的树进行调整
(1)LL型不平衡(需右单旋转)
在某个子树的左子树的左子树上插入新节点,导致根节点的平衡因子由1变为2
treeNode* rightRotate(treeNode* root)
{
/*
root x
/ \ / \
x o2 -> O root
/ \ / \
O o1 o1 o2
*/
treeNode* x=root->leftSon;
treeNode* o1=x->rightSon;
x->rightSon=root;
root->leftSon=o1;
root->height=getHeight(root);
x->height=getHeight(x);
return x;
}
(2)RR型不平衡(需左单旋转)
在某个子树的右子树的右子树上插入新节点,导致根节点的平衡因子由-1变为-2
treeNode* leftRotate(treeNode* root)
{
/*
root x
/ \ / \
o1 x -> root O
/ \ / \
o2 O o1 o2
*/
treeNode* x=root->rightSon;
treeNode* o2=x->leftSon;
x->leftSon=root;
root->rightSon=o2;
root->height=getHeight(root);
x->height=getHeight(x);
return x;
}
(3)LR型不平衡(需左右双旋转)
在某个子树的左子树的右子树上插入新节点,导致根节点的平衡因子由1变为2
先调用再 leftRotate(root->leftSon) 调用 rightRotate(root)
treeNode* left_rightRotate(treeNode* root)
{
/*
root root y
/ \ / \ / \
x o2 -> y o2 -> x root
/ \ / \ / \ / \
o1 y x O2 o1 O1 O2 o2
/ \ / \
O1 O2 o1 O1
*/
root->leftSon=leftRotate(root->leftSon);
return rightRotate(root);
}
(4)RL型不平衡(需右左双旋转)
在某个子树的右子树的左子树上插入新节点,导致根节点的平衡因子由-1变为-2
treeNode* right_leftRotate(treeNode* root)
{
/*
root root y
/ \ / \ / \
o1 x -> o1 y -> root x
/ \ / \ / \ / \
y o2 O1 x o1 O1 O2 o2
/ \ / \
O1 O2 O2 o2
*/
root->rightSon=rightRotate(root->rightSon);
return leftRotate(root);
}
3、插入
Height的获取
int getHeight(treeNode* root)
{
if(root==NULL)
return 0;
return 1+max(getHeight(root->leftSon),getHeight(root->rightSon));
}
创建新节点
treeNode* createTreeNode(int value)
{
treeNode* node=new treeNode;
node->data=value;
node->height=0;
node->leftSon=NULL;
node->rightSon=NULL;
return node;
};
获取平衡因子
int getBalanceFactor(treeNode* root)
{
if(root==NULL)
return 0;
return getHeight(root->leftSon)-getHeight(root->rightSon);
}
插入新节点
treeNode* insertNode(treeNode* root,int value)
{
if(root==NULL)
return createTreeNode(value);
if(value<root->data)
root->leftSon=insertNode(root->leftSon,value);
else if(value>root->data)
root->rightSon=insertNode(root->rightSon,value);
else
return root;
//调整平衡为AVL树
root->height=getHeight(root);
int bf=getBalanceFactor(root);
//LL型
if(bf>1&&value<root->leftSon->data)
return rightRotate(root);
//RR型
if(bf<-1&&value>root->rightSon->data)
return leftRotate(root);
//LR型
if(bf>1&&value>root->leftSon->data)
return left_rightRotate(root);
//RL型
if(bf<-1&&value<root->rightSon->data)
return right_leftRotate(root);
return root;
}