显示旋转过程的AVL树
来源:互联网 发布:sor文件打开软件 编辑:程序博客网 时间:2024/05/16 05:00
这是我第一次在csdn上面写博客。以前遇到不会的问题时,csdn总有一片博文能为我解惑,今天我也打算上传一些代码来为这个社区做贡献。笔者不才,代码常有纰漏之处,愿有幸读到这篇博文的同学不吝赐教。
下面的代码是一颗AVL树的插入代码,随着插入的进行,树会根据左右子树的高度来进行调整,并且会把步骤显示出来,不过步骤的显示并没有独立做成函数,而是嵌在代码中,这在一定程度上影响了程序的可读性,读者可以先把cout部分的代码略去,以观察旋转过程。需要提醒,旋转的函数我用了c++里面的引用,所以并没有传值出去,函数类型为void。
#include<cctype>#include<iostream>#include<stack>#include<queue>#include<array>typedef struct TNode *BinTree;struct TNode{//树的结点的结构体,包含一个整数数值,指向左子树的指针,指向右子树的指针,和该结点的高度 int data;BinTree left;BinTree right;int height;};using namespace std;int GetHeight(BinTree BT) //该函数功能是读取该节点的高度并返回该值 {if( !BT ) return 0;else{return (GetHeight(BT->left) > GetHeight(BT->right) ? GetHeight(BT->left) :GetHeight(BT->right) )+1;}}void Sgl_left(BinTree &BT) //左单旋的过程,如果觉得不易阅读可以先忽略掉cout开头的语句 {BinTree tmp = BT->left;cout<<tmp->data<<"的右子树移到 "<<BT->data<<" 的左子树\n";cout<<"结点 "<<BT->data<<" 移到结点 "<<tmp->data<<" 的右子树"<<endl<<endl; BT->left = tmp->right;tmp->right = BT;BT = tmp;//注意在每次旋转过后都要更新结点的高度 BT->height = (GetHeight(BT->left) > GetHeight(BT->right) ? GetHeight(BT->left):GetHeight(BT->right))+1;}void Sgl_right(BinTree &BT){BinTree tmp = BT->right;cout<<tmp->data<<"的左子树移到 "<<BT->data<<" 的右子树\n";cout<<"结点 "<<BT->data<<" 移到结点 "<<tmp->data<<" 的左子树"<<endl<<endl; BT->right = tmp->left; tmp->left = BT;BT = tmp;BT->height = (GetHeight(BT->left) > GetHeight(BT->right) ? GetHeight(BT->left):GetHeight(BT->right))+1;}void Dbl_left_right(BinTree &BT)//左右双旋 {BinTree &tmp = BT->left;Sgl_right(tmp);Sgl_left(BT);}void Dbl_right_left(BinTree &BT)//右左双旋 {BinTree &tmp = BT->right;Sgl_left(tmp);Sgl_right(BT);}BinTree AVL_insert(BinTree BT,int data){if(!BT) //如果结点空,说明找到了该插入的位置,那么,插入之。 {BT = new TNode;BT->data = data;BT->height = 0;BT->left = BT->right = NULL;}else{if( data > BT->data) //值比该结点的要大,递归插入到该结点的右子树 {BT->right = AVL_insert(BT->right,data);if(GetHeight(BT->left) - GetHeight(BT->right) == -2)//插入完成后判断树是否平衡,如果不平衡,先判断如何旋转,再调用函数旋转 {cout<<"根为 "<<BT->data<<" 的树右子树高度比左子树低2," ; if(data > BT->right->data) {cout<<"插入的节点的值 "<<data<<" 比树根为 "<<BT->data<<" 的树的右子树的值要大!\n"<<"所以进行右单旋\n"; Sgl_right(BT);}else{cout<<"插入的节点的值 "<<data<<" 比树根为 "<<BT->data<<" 的树的右子树的值要小!\n"<<"所以进行右左双旋\n"; Dbl_right_left(BT);} }}else if(data < BT->data) //如果待插入的值比该结点小,则递归的插入到该节点的右子树 {BT->left = AVL_insert(BT->left,data);if(GetHeight(BT->left) - GetHeight(BT->right) == 2){cout<<"根为 "<<BT->data<<" 的树左子树高度比右子树高2," ; if(data < BT->left->data ){cout<<"插入的节点的值 "<<data<<" 比树根为 "<<BT->data<<" 的树的左子树的值要小!\n"<<"所以进行左单旋\n"; Sgl_left(BT);}else{cout<<"插入的节点的值 "<<data<<" 比树根为 "<<BT->data<<" 的树的左子树的值要大!\n"<<"所以进行左右双旋\n"; Dbl_left_right(BT);} }}}//更新结点的高度 int max = (GetHeight(BT->left) > GetHeight(BT->right) ? GetHeight(BT->left):GetHeight(BT->right))+1;BT->height = max;return BT;}//层序遍历 void Level_trav(BinTree BT){queue<BinTree>q;q.push(BT);BinTree Tmp = NULL;while( !q.empty()){Tmp = q.front();q.pop();cout<<Tmp->data<<" ";if(Tmp->left) q.push(Tmp->left);if(Tmp->right) q.push(Tmp->right);}}int main(){int tmp ;BinTree BT = NULL;//这是测试数据 array<int,20> test = {12,9,7,6,8,49,63,34,77,-7,0,83,88,106,-79,-63,32,7,49,-49}; for(int i = 0;i<20;i++){cout<<"第"<<i+1<<"个结点:"<<test[i]<<endl<<endl; BT = AVL_insert(BT,test[i]);}cout<<"层序遍历这棵树:";Level_trav(BT);return 0;}
阅读全文