由于二叉排序树插入随意,毫无规则可言,自然时间效率就不能保证,极端情况下会退化成链表(左空右慢或反之)。
平衡二叉树就是在二叉排序树的基础上进行优化,平衡二叉树就是保证任何父节点的左右子树深度只能相差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 */