篇一:二叉树-遍历终极版
篇二:二叉树-创建、重建、转化
篇三:二叉树-详解二叉排序树
篇四:二叉树-详解平衡二叉树AVL
篇五:二叉树-常见简单算法题
也许因为输入值不够随机,也许因为输入顺序的原因,还或许一些插入、删除操作,会使得二叉搜索树失去平衡,造成搜索效率低落的情况。
那么什么叫“平衡”,直观上的最佳平衡条件就是 每个节点的左右子树有着相同高度,但这确实太过苛刻。平衡二叉树AVL tree退而求其次,要求任何节点的左右节点的左右子树高度差不超过1。
定义平衡二叉树结构:
typedef struct BBSTNode
{
int data;
int bf;
struct BBSTNode*lchild, *rchild;
}AVLNode, *AVLTree;
封装二叉排序树类:
class CAVLTree{
private:
//供内部调用的函数
int GetAVLHight(AVLTree T);//求得树的高度
void setHeight(AVLTree, int);//设置节点的高度值
//单旋转,右右插入导致的不平衡,左旋操作
void LL_RRotate(AVLTree *T);
//单旋转,右右插入导致的不平衡,左旋操作
void RR_LRotate(AVLTree *T);
//双旋转,左右插入导致的不平衡
void LR_Rotate(AVLTree *T);
//双旋转,右左插入导致的不平衡
void RL_Rotate(AVLTree *T);
public:
//默认构造函数
CAVLTree();
//析构函数
~CAVLTree();
//创建AVL树
void createAVLTree(int a[], int n);
//删除树
void deleteTree(AVLTree t);
//插入节点
AVLTree insertNode(AVLTree T, int val);
//删除树中元素值等于某值的节点
AVLTree deleteNode(AVLTree T, const int val);
//搜寻元素值等于某值的节点
AVLTree searchNode(AVLTree T, int val);
//前序遍历输出树
void PreOrderTraverse(AVLTree T);
//得到树中的元素值最大的节点
AVLTree FindMaxAVL(AVLTree T);
//得到树中的元素值最小的那个节点
AVLTree FindMinAVL(AVLTree T);
AVLTree T;
};
举个因为插入元素使得平衡二叉树不平衡的情况:
上述只是平衡被破坏的一种情况,这种情况是“左左插入”,还有三种情况(假设最深节点为X):
对于上面四中情况,我们再分一下类,可以分为两类:
1、外侧插入:左左、右右,很容易理解,都是在最边边上。
2、内侧插入:左右、右左,也很容易理解,网里面来了些。
对于上面说到的外侧插入,我们可以采用单旋转操作调整解决;对于内侧插入,我们可以双旋转操作解决。
先上个单旋转图,再慢慢解释:
为什么这么做了,我们来回想一下二叉排序树的性质
1、根据性质我们知道,k2>k1,所以k2必须成为新树形中的k1节点的右子节点。(k1向上提起,使k2自然下滑)
2、同样根据性质,我们知道B子树的所有节点的键值都在k1和k2之间,也就是大于k1,小于k2,那不就是在k1的右子树上,k2的左子树上,因此将B子树挂到k2的左侧(将B子树挂到k2的左侧)。
最终调整后的图如上右图,这是“左左”,“右右”跟这情况一样。
单旋转,左左插入导致的不平衡,右旋操作:
void CAVLTree::LL_RRotate(AVLTree *p)
{
AVLTree N = (*p)->lchild;
(*p)->lchild = N->rchild;
N->rchild = (*p);
*p = N;
}
单旋转,右右插入导致的不平衡,左旋操作:
void CAVLTree::RR_LRotate(AVLTree *p)
{
AVLTree N = (*p)->rchild;
(*p)->rchild = N->lchild;
N->lchild = (*p);
*p = N;
}
先上图,再解释:
双旋转,左右插入导致的不平衡:
void CAVLTree::LR_Rotate(AVLTree *p)
{
//双旋转可以通过两次单旋转实现
//对p的左结点进行RR旋转,再对根节点进行LL旋转
RR_LRotate(&(*p)->lchild);
LL_RRotate(p);
}
双旋转,右左插入导致的不平衡:
void CAVLTree::RL_Rotate(AVLTree *p)
{
LL_RRotate(&(*p)->rchild);
RR_LRotate(p);
}
平衡二叉排序树的插入跟二叉排序树不同,它不能让二叉排序树失去平衡,代码如下:
AVLTree CAVLTree::insertNode(AVLTree T, int val)
{
AVLNode *pNewNode = new AVLNode;
pNewNode->data = val;
pNewNode->lchild = NULL;
pNewNode->rchild = NULL;
if (NULL == T)
{
T = pNewNode;
return T;
}
//需要插入节点的树非空
//插入的元素已经存在于树中,不符合要求
if (val == T->data)
{
cout << "元素中有重复,构建AVL树失败!" << endl;
return T;
}
//要插入的值小于根节点的值,将其插入左子树中
if (val < T->data)
{
//将其插入根节点的左子树中
T->lchild = insertNode(T->lchild, val);
//判断平衡条件是否仍然满足
if (GetAVLHight(T->lchild) - GetAVLHight(T->rchild) > 1)
{
//分两种情况进行旋转操作
//插入点位于T的左子结点的左子树
if (val < T->lchild->data)
//实施单旋转-右旋转
LL_RRotate(&T);
else
//插入点位于T的左子结点的右子树,实施双右旋转
LR_Rotate(&T);
}
}
//要插入的值大于根节点的值,将其插入右子树中
if (val > T->data)
{
T->rchild = insertNode(T->rchild, val);
//判断平衡条件是否仍然满足
if (GetAVLHight(T->rchild) - GetAVLHight(T->lchild) > 1)
{
//节点插入到T的右子节点的右子树中
if (val > T->rchild->data)
//实施单旋转-左旋转
RR_LRotate(&T);
else
//节点插入到T的右子节点的左子树上
//实施双旋转-左旋转
RL_Rotate(&T);
}
}
return T;
}
AVLTree CAVLTree::deleteNode(AVLTree root, const int val)
{
if (!root)
{
cout << "The tree is NULL, delete failed" << endl;
return root;
}
AVLTree searchedNode = searchNode(root, val);
//没有找到相应的节点,删除失败
if (!searchedNode)
{
cout << "Cann't find the node to delete " << val << endl;
return root;
}
//找到了需要删除的节点
//需要删除的节点就是当前子树的根节点
if (val == root->data)
{
//左右子树都非空
if (root->lchild && root->rchild)
{
//在高度更大的那个子树上进行删除操作
if (GetAVLHight(root->lchild) > GetAVLHight(root->rchild))
{
//左子树高度大,删除左子树中元素值最大的那个节点,同时将其值赋值给根节点
root->data = FindMaxAVL(root->lchild)->data;
root->lchild = deleteNode(root->lchild, root->data);
}
else{
//删除右子树中元素值最小的那个节点,同时将其值赋值给根节点
root->data = FindMinAVL(root->rchild)->data;
root->rchild = deleteNode(root->rchild, root->data);
}
}
else{
//左右子树中有一个不为空,那个直接用需要被删除的节点的子节点替换之即可
AVLTree oldNode = root;
root = (root->lchild ? root->lchild : root->rchild);
delete oldNode;//释放节点所占的空间
oldNode = NULL;
}
}
else if (val < root->data)//要删除的节点在左子树中
{
//在左子树中进行递归删除
root->lchild = deleteNode(root->lchild, val);
//判断是否仍然满足平衡条件
if (GetAVLHight(root->rchild) - GetAVLHight(root->lchild) > 1)
{
if (root->rchild->lchild > root->rchild->rchild)
{
//左双旋转
RL_Rotate(&root);
}
else//进行左单旋转
RR_LRotate(&root);
}
}
else//需要删除的节点在右子树中
{
root->rchild = deleteNode(root->rchild, val);
//判断是否满足平衡条件
if (GetAVLHight(root->lchild) - GetAVLHight(root->rchild) > 1)
{
if (GetAVLHight(root->lchild->rchild) > GetAVLHight(root->lchild->lchild))
//右双旋转
LR_Rotate(&root);
else
//右单旋转
LL_RRotate(&root);
}
}
return root;
}
1、求树的高度
int CAVLTree::GetAVLHight(AVLTree T)
{
if (T == NULL)
return 0;
else
{
int left = GetAVLHight(T->lchild);
int right = GetAVLHight(T->rchild);
return 1 + max(left, right);
}
}
2、查找节点
AVLTree CAVLTree::searchNode(AVLTree root, int val)
{
if (!root) return NULL;
//搜索到
if (val == root->data)
return T;
else if (val <root->data)
{
//在左子树中搜索
return searchNode(root->lchild, val);
}
else
{
//在右子树中搜索
return searchNode(root->rchild, val);
}
}
3、查找最大最小元素
AVLTree CAVLTree::FindMaxAVL(AVLTree p)
{
if (NULL==p) return NULL;
if (p->rchild == NULL)
return p;
return FindMaxAVL(p->rchild);
}
AVLTree CAVLTree::FindMinAVL(AVLTree p)
{
if (NULL == p)
return NULL;
if (p->lchild == NULL)
return p;
return FindMinAVL(p->lchild);
}
4、先序遍历
void CAVLTree::PreOrderTraverse(AVLTree T)
{
if (T)
{
cout << T->data << " ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
#include
#include
using namespace std;
//平衡二叉排序树
typedef struct BBSTNode
{
int data;
int bf;
struct BBSTNode*lchild, *rchild;
}AVLNode, *AVLTree;
//AVL tree类封装
class CAVLTree{
private:
//供内部调用的函数
int GetAVLHight(AVLTree T);//求得树的高度
void setHeight(AVLTree, int);//设置节点的高度值
//单旋转,右右插入导致的不平衡,左旋操作
void LL_RRotate(AVLTree *T);
//单旋转,右右插入导致的不平衡,左旋操作
void RR_LRotate(AVLTree *T);
//双旋转,左右插入导致的不平衡
void LR_Rotate(AVLTree *T);
//双旋转,右左插入导致的不平衡
void RL_Rotate(AVLTree *T);
public:
//默认构造函数
CAVLTree();
//析构函数
~CAVLTree();
//创建AVL树
void createAVLTree(int a[], int n);
//删除树
void deleteTree(AVLTree t);
//插入节点
AVLTree insertNode(AVLTree T, int val);
//删除树中元素值等于某值的节点
AVLTree deleteNode(AVLTree T, const int val);
//搜寻元素值等于某值的节点
AVLTree searchNode(AVLTree T, int val);
//前序遍历输出树
void PreOrderTraverse(AVLTree T);
//得到树中的元素值最大的节点
AVLTree FindMaxAVL(AVLTree T);
//得到树中的元素值最小的那个节点
AVLTree FindMinAVL(AVLTree T);
AVLTree T;
};
CAVLTree::CAVLTree()
{
T = NULL;
}
CAVLTree::~CAVLTree()
{
deleteTree(T);
}
void CAVLTree::deleteTree(AVLTree t)
{
if (NULL == t)
return;
deleteTree(t->lchild);
deleteTree(t->rchild);
delete t;
t = NULL;
}
// 对于实例,我们可以这样创建平衡二叉树
void CAVLTree::createAVLTree(int a[], int n)
{
if (T) return;
for (int i = 0; i<5; i++)
{
T=insertNode(T, a[i]);
}
}
//单旋转,左左插入导致的不平衡,右旋操作
void CAVLTree::LL_RRotate(AVLTree *p)
{
AVLTree N = (*p)->lchild;
(*p)->lchild = N->rchild;
N->rchild = (*p);
*p = N;
}
//单旋转,右右插入导致的不平衡,左旋操作
void CAVLTree::RR_LRotate(AVLTree *p)
{
AVLTree N = (*p)->rchild;
(*p)->rchild = N->lchild;
N->lchild = (*p);
*p = N;
}
//双旋转,左右插入导致的不平衡
void CAVLTree::LR_Rotate(AVLTree *p)
{
//双旋转可以通过两次单旋转实现
//对p的左结点进行RR旋转,再对根节点进行LL旋转
RR_LRotate(&(*p)->lchild);
LL_RRotate(p);
}
//双旋转,右左插入导致的不平衡
void CAVLTree::RL_Rotate(AVLTree *p)
{
LL_RRotate(&(*p)->rchild);
RR_LRotate(p);
}
//求二叉树的高度
int CAVLTree::GetAVLHight(AVLTree T)
{
if (T == NULL)
return 0;
else
{
int left = GetAVLHight(T->lchild);
int right = GetAVLHight(T->rchild);
return 1 + max(left, right);
}
}
//查找元素,找到返回关键字的结点指针,没找到返回NULL
AVLTree CAVLTree::searchNode(AVLTree root, int val)
{
if (!root) return NULL;
//搜索到
if (val == root->data)
return T;
else if (val <root->data)
{
//在左子树中搜索
return searchNode(root->lchild, val);
}
else
{
//在右子树中搜索
return searchNode(root->rchild, val);
}
}
AVLTree CAVLTree::FindMaxAVL(AVLTree p)
{
if (NULL==p) return NULL;
if (p->rchild == NULL)
return p;
return FindMaxAVL(p->rchild);
}
AVLTree CAVLTree::FindMinAVL(AVLTree p)
{
if (NULL == p)
return NULL;
if (p->lchild == NULL)
return p;
return FindMinAVL(p->lchild);
}
// 先序遍历
void CAVLTree::PreOrderTraverse(AVLTree T)
{
if (T)
{
cout << T->data << " ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
AVLTree CAVLTree::insertNode(AVLTree T, int val)
{
AVLNode *pNewNode = new AVLNode;
pNewNode->data = val;
pNewNode->lchild = NULL;
pNewNode->rchild = NULL;
if (NULL == T)
{
T = pNewNode;
return T;
}
//需要插入节点的树非空
//插入的元素已经存在于树中,不符合要求
if (val == T->data)
{
cout << "元素中有重复,构建AVL树失败!" << endl;
return T;
}
//要插入的值小于根节点的值,将其插入左子树中
if (val < T->data)
{
//将其插入根节点的左子树中
T->lchild = insertNode(T->lchild, val);
//判断平衡条件是否仍然满足
if (GetAVLHight(T->lchild) - GetAVLHight(T->rchild) > 1)
{
//分两种情况进行旋转操作
//插入点位于T的左子结点的左子树
if (val < T->lchild->data)
//实施单旋转-右旋转
LL_RRotate(&T);
else
//插入点位于T的左子结点的右子树,实施双右旋转
LR_Rotate(&T);
}
}
//要插入的值大于根节点的值,将其插入右子树中
if (val > T->data)
{
T->rchild = insertNode(T->rchild, val);
//判断平衡条件是否仍然满足
if (GetAVLHight(T->rchild) - GetAVLHight(T->lchild) > 1)
{
//节点插入到T的右子节点的右子树中
if (val > T->rchild->data)
//实施单旋转-左旋转
RR_LRotate(&T);
else
//节点插入到T的右子节点的左子树上
//实施双旋转-左旋转
RL_Rotate(&T);
}
}
return T;
}
AVLTree CAVLTree::deleteNode(AVLTree root, const int val)
{
if (!root)
{
cout << "The tree is NULL, delete failed" << endl;
return root;
}
AVLTree searchedNode = searchNode(root, val);
//没有找到相应的节点,删除失败
if (!searchedNode)
{
cout << "Cann't find the node to delete " << val << endl;
return root;
}
//找到了需要删除的节点
//需要删除的节点就是当前子树的根节点
if (val == root->data)
{
//左右子树都非空
if (root->lchild && root->rchild)
{
//在高度更大的那个子树上进行删除操作
if (GetAVLHight(root->lchild) > GetAVLHight(root->rchild))
{
//左子树高度大,删除左子树中元素值最大的那个节点,同时将其值赋值给根节点
root->data = FindMaxAVL(root->lchild)->data;
root->lchild = deleteNode(root->lchild, root->data);
}
else{
//删除右子树中元素值最小的那个节点,同时将其值赋值给根节点
root->data = FindMinAVL(root->rchild)->data;
root->rchild = deleteNode(root->rchild, root->data);
}
}
else{
//左右子树中有一个不为空,那个直接用需要被删除的节点的子节点替换之即可
AVLTree oldNode = root;
root = (root->lchild ? root->lchild : root->rchild);
delete oldNode;//释放节点所占的空间
oldNode = NULL;
}
}
else if (val < root->data)//要删除的节点在左子树中
{
//在左子树中进行递归删除
root->lchild = deleteNode(root->lchild, val);
//判断是否仍然满足平衡条件
if (GetAVLHight(root->rchild) - GetAVLHight(root->lchild) > 1)
{
if (root->rchild->lchild > root->rchild->rchild)
{
//左双旋转
RL_Rotate(&root);
}
else//进行左单旋转
RR_LRotate(&root);
}
}
else//需要删除的节点在右子树中
{
root->rchild = deleteNode(root->rchild, val);
//判断是否满足平衡条件
if (GetAVLHight(root->lchild) - GetAVLHight(root->rchild) > 1)
{
if (GetAVLHight(root->lchild->rchild) > GetAVLHight(root->lchild->lchild))
//右双旋转
LR_Rotate(&root);
else
//右单旋转
LL_RRotate(&root);
}
}
return root;
}
int main()
{
int arr[] = {18,14,20,12,16};
CAVLTree *CAVLTreeObj1 = new CAVLTree();
CAVLTreeObj1->createAVLTree( arr, 5);
cout << "AVL Tree先序遍历结果:" << endl;
CAVLTreeObj1->PreOrderTraverse(CAVLTreeObj1->T);
cout << endl;
int insertedVal1 = 11;
CAVLTreeObj1->T = CAVLTreeObj1->insertNode(CAVLTreeObj1->T, insertedVal1);
cout << "向AVL树中插入元素 " << insertedVal1 << "之后的先序遍历结果:" << endl;
CAVLTreeObj1->PreOrderTraverse(CAVLTreeObj1->T);
cout << endl;
const int deletedVal2 = 18;
CAVLTreeObj1->T = CAVLTreeObj1->deleteNode(CAVLTreeObj1->T, deletedVal2);
cout << "删除元素值为 " << deletedVal2 << "的节点之后的树先序遍历结果:" << endl;
CAVLTreeObj1->PreOrderTraverse(CAVLTreeObj1->T);
cout << endl;
}