您的位置:首页 > 其它

二叉排序树第二版(平衡二叉树)

2015-11-05 20:03 211 查看
由于二叉排序树插入随意,毫无规则可言,自然时间效率就不能保证,极端情况下会退化成链表(左空右慢或反之)。

平衡二叉树就是在二叉排序树的基础上进行优化,平衡二叉树就是保证任何父节点的左右子树深度只能相差1、0、-1(左-右),所以每次插入一个新点都要修改这棵树使其平衡,学名叫旋转(其实不像旋转),这样效率就能达到log(n)。旋转的讲解 http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html 这里写很好, 不过代码有些问题。

附上完整代码,没有写成类模板。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>

using namespace std;
typedef int type;
const int BF=2;
struct tree
{
type data;
int h;  //深度
int howmany; //  相等的记录
tree *left,*right,*father;
}*root;

inline int max(int a,int b)
{
if(a>b) return a;
else return b;
}
inline int height(tree *node)
{
if(node) return node->h;
else return 0;
}
void initnode(tree *node)
{
node->h=0;
node->howmany=1;
node->left=NULL;
node->right=NULL;
node->father=NULL;
}
void changeNode(tree *s,tree *t)  //  son  temp;
{
if(s->father)
{
tree *r=s->father;
if(r->left == s)
{
r->left = t;
t->father = r;
}
else
{
r->right = t;
t->father = r;
}
}
else
{
root = t;
t->father = NULL;
}
s->father=t;
}
void AdjustLeftLeft(tree *son)
{
tree *temp;
temp = son->left;
son->left = temp->right;
if(temp->right) temp->right->father = son;
temp->right = son;

changeNode(son,temp);     //  更新父节点的指向

int lh=height(son->left);
int rh=height(son->right);
son->h = lh > rh ? lh+1 : rh+1;  //  更新高度
lh=height(temp->left);
temp->h = lh > son->h ? lh+1 : son->h+1;
}
void AdjustRightRight(tree *son)
{
tree *temp;
temp = son->right;
son->right = temp->left;
if(temp->left) temp->left->father = son;
temp->left = son;

changeNode(son,temp);

int lh=height(son->left);             //  和上面是雷同代码   可以写成函数
int rh=height(son->right);
son->h = lh > rh ? lh+1 : rh+1;  //  更新高度
lh=height(temp->left);
temp->h = lh > son->h ? lh+1 : son->h+1;
}
void AdjustLeftRight(tree *son)
{
AdjustRightRight(son->left);
AdjustLeftLeft(son);
}
void AdjustRightLeft(tree *son)
{
AdjustLeftLeft(son->right);
AdjustRightRight(son);
}
void insertnode(tree *&node,const type x,tree *f)   //   这里传引用,  空指针实参传过来无用
{
if(node==NULL)
{
node=new tree;
if(node == NULL)
{
cout<<"no  memery!"<<endl;
exit(0);
}
node->data=x;
initnode(node);
node->father=f;
}
else if(node->data > x)  // 放在左子树
{
insertnode(node->left,x,node);
if(height(node->left) -height(node->right) == BF)   //  这如果不写成函数  就容易报空指针异常! 学着点
{
if(node->left->data > x)
AdjustLeftLeft(node);
else
AdjustLeftRight(node);
}
}
else if(node->data < x)
{
insertnode(node->right,x,node);
if(height(node->right) - height(node->left) == BF)
{
if(node->right->data < x)
AdjustRightRight(node);
else
AdjustRightLeft(node);
}
}
else if(node->data == x) node->howmany++;
int i,j;
if(node->left == NULL) i=0;
else i=node->left->h;
if(node->right == NULL) j=0;
else j=node->right->h;
node->h = max(i,j)+1;
}
void midorder(tree *r)
{
if(r->left) midorder(r->left);
for(int i=1;i<=r->howmany;i++)
cout<<r->data<<" ";
if(r->right) midorder(r->right);
}
void DeleteAll(tree *node)
{
if(node->right) DeleteAll(node->right);
if(node->left) DeleteAll(node->left);
delete node;
}
void DeleteNode(tree *node,type x)
{
if(node == NULL)
{
printf("无此点 \n");
return;
}
else if(x > node->data)    //  删除右子树中的节点,如果需要平衡只可能是左左或左右这两种情况
{
DeleteNode(node->right,x);
if(height(node->right) - height(node->left) == BF)
{
if(height(node->left->left) > height(node->left->right))  //  这需要判空吗?  应该不用
AdjustLeftLeft(node);
else
AdjustLeftRight(node);
}
}
else if(x < node->data)
{
DeleteNode(node->left,x);
if(height(node->left) - height(node->right) == BF)
{
if(height(node->right->right) > height(node->right->left))
AdjustRightRight(node);
else
AdjustRightLeft(node);
}
}
else
{
tree *temp1,*temp2;
if(node->howmany > 1)   //  如果这个数不是一个  什么都不用干 删次数就好了
{
node->howmany--;
return;
}
else if(node->left && node->right)   //  删除的点有两个儿子
{
temp1 = node->right;
while(temp1->left)
{
int h1=height(temp1->left)-1;
int h2=height(temp1->right);
temp1->h = h1>h2 ? h1:h2; //  拿出节点就要更新高度
temp1 = temp1->left;  //  找到右子树最小值 准备替换。
}
node->data=temp1->data;
temp2 = temp1->father;
temp2->left=NULL;
delete temp1;
if(height(node->left) - height(node->right) == BF)
{
if(height(node->left->left) > height(node->left->right))
AdjustLeftLeft(node);
else
AdjustLeftRight(node);
}
//  没落什么吧
}
else    //  0或1个儿子
{
if(node->howmany > 1)
{
node->howmany--;
return ;
}
else
{
if(node->left) temp1=node->left;
else temp1=node->right;
if(temp1)
{
node->data = temp1->data;
node->h--;
node->left = node->right = NULL;
delete temp1;
}
else
{
temp2 = node->father;
if(temp2->left == node) temp2->left = NULL;
else temp2->right = NULL;
delete node;
}
return ;
}
}
int hl = height(node->left);   //  回朔的节点全部更新一下高度
int hr = height(node->right);
node->h = hr>hl ? hr:hl;
}
}
bool searchnode(tree *node,type x)   //  查找
{
if(node->data == x)
{
return true;
}
else if(node->data > x)
{
return searchnode(node->left,x);
}
else
{
return searchnode(node->right,x);
}
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int a;
scanf("%d",&a);
insertnode(root,a,NULL);
}
midorder(root);
cout<<endl;
DeleteNode(root,5);
midorder(root);
DeleteAll(root);
return 0;
}

/*
10
8 4 5 7 6 9 2 1 3 0
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: