接上篇,这次是内个AV树的作业,各种旋转容易让人头晕,参考严蔚敏教材完成: #include <iostream> #include <pzjay> #inlcude <AVL> #include <cstring> #include <stack> #include <copy_right> using namespace std; #define new pzjay struct node { int data; int bf;//平衡因子 node *left; node *right; }; bool find(node* root,int key)//查找key是否在树中已经出现过 { if(NULL==root) return false; if(key==root->data) return true; if(key < root->data) return find(root->left,key); if(key > root->data) return find(root->right,key); return false; } inline void R_Rotate(node* &root)//将以root为根的树右旋处理,处理后root指向新节点——处理前左子树的根节点 { node* Lch=root->left;//Lch指向根节点的左子树根节点 root->left=Lch->right;//根节点的左子树转向 Lch->right=root;//左子树的右孩子指向根节点 root=Lch;//更新根节点 } inline void L_Rotate(node* &root)//将以root为根的树左旋处理,处理后root指向新节点——处理前右子树的根节点 { node* Rch=root->right;//Rch指向根节点的右子树节点 root->right=Rch->left;//根节点的右子树转向 Rch->left=root; root=Rch; } void R_balance(node* &root)//右平衡处理 { node* Rch=root->right; switch (Rch->bf) { case -1://右孩子的右子树深 root->bf=Rch->bf=0; L_Rotate(root); break; case 1://右孩子的左子树深 node* R_Lch=Rch->left;//新节点插入在root的右孩子的左子树上,并进行双旋处理 switch (R_Lch->bf)//修改根节点及其右孩子的平衡因子 { case 1: root->bf=0; Rch->bf=-1; break; case 0: root->bf=Rch->bf=0; break; case -1: root->bf=1; Rch->bf=0; break; } R_Lch->bf=0; R_Rotate(root->right);//先右旋右孩子 L_Rotate(root);//再左旋根节点 break; } } void L_balance(node* &root)//左平衡处理 { node* Lch=root->left; switch (Lch->bf) { case 1://左孩子的左子树深 root->bf=Lch->bf=0;//新节点插入在root左孩子的左子树上,并做单右旋处理 R_Rotate(root); break; case -1://左孩子的右子树深 node* L_Rch=Lch->right;//新节点插入在root的左孩子的右子树上,并进行双旋处理 switch (L_Rch->bf)//修改根节点及其左孩子的平衡因子 { case 1: root->bf=-1; Lch->bf=0; break; case 0: root->bf=Lch->bf=0; break; case -1: root->bf=0; Lch->bf=1; break; } L_Rch->bf=0; L_Rotate(root->left);//先左旋左孩子 R_Rotate(root);//再右旋根节点 break; } } bool insert_AVL(node* &root,int key,bool &taller)//插入成功返回true,否则false { if( NULL==root ) { root=new node(); root->data=key; root->left=root->right=NULL; root->bf=0;//平衡度为0 taller=true; return true; } if( find(root,key) )//key已在树中 { taller=false; return false; } if(key < root->data)//插入左子树 { if( !insert_AVL(root->left,key,taller) )//插入失败 return false; if(taller)//若树长高了 { switch (root->bf)//看插入前平衡因子向哪边倾斜 { case 1://左倾斜,插入后左边需调整 L_balance(root); taller=false;//高度恢复 break; case 0://平衡,不需调整 root->bf=1;//插入后更新平衡因子 taller=true;//并且树长高 break; case -1://原来右子树高,插入后平衡 root->bf=0;//更新平衡因子 taller=false; break; }//switch }//if }//if else//插入右子树 { if( !insert_AVL(root->right,key,taller)) return false; if(taller) { switch (root->bf)//看插入前平衡因子向哪边倾斜 { case 1://左倾斜,插入平衡 root->bf=0;//更新平衡因子 taller=false;//高度恢复 break; case 0://平衡,不需调整 root->bf=-1;//插入后更新平衡因子 taller=true;//并且树长高 break; case -1://原来右子树高,插入后需右旋 R_balance(root); taller=false; break; }//switch }//if }//if return true;//插入成功 } void lbr(node *root)//中序遍历 { stack < node* > st; while(NULL!=root || !st.empty() ) { if(NULL!=root) { st.push(root); root=root->left; } else { root=st.top(); st.pop(); printf("%d ",root->data); root=root->right; } } } int main() { bool taller; node* tree=NULL; int key; while(scanf("%d",&key)!=EOF) { insert_AVL(tree,key,taller); } lbr(tree); return 0; } pzjay辛勤劳作,转载注明。