AVL平衡二叉树打印树模型测试

来源:互联网 发布:尚德科技 互助平台源码 编辑:程序博客网 时间:2024/05/21 22:50

对于树模型,大家比较熟知的就是AVL树和红黑树。前者利用树的高度来严格的保证左右子树的高度差不超过1,而后者则利用着色和一系列规则确保树的平衡:左右子树高度差不超过2。本篇文章主要讨论AVL树,并打印出树的结构模型,以便观察树在插入和删除元素后树的变化。


一、代码

1、AvlTree.h

<span style="font-family:Microsoft YaHei;">#ifndef __AVL_TREE__#define __AVL_TREE__#include "printTree.h"#include<iomanip>template <typename Type>class AvlTree{public:struct AvlNode{Type element;AvlNode*left;AvlNode*right;intheight; AvlNode( const Type& dt, AvlNode *lt, AvlNode *rt, int h = 0 ) : element(dt), left(lt), right(rt), height(h){}};private:AvlNode *root;int   size;friend class PrintTree<Type, AvlNode, AvlTree>;PrintTree<Type, AvlNode, AvlTree> ptta;int height( AvlNode *t ){return ( t == NULL ) ? -1 : t -> height;}int max( int x, int y ){return x > y ? x : y;}void right_rotate( AvlNode* &t ){AvlNode *k = t -> left;t -> left = k -> right;k -> right = t;t -> height = max( height( t -> left ), height( t -> right ) ) + 1;k -> height = max( height( k -> left ), t -> height ) + 1;t = k;}void left_rotate( AvlNode* &t ){AvlNode *k = t -> right;t -> right = k -> left;k -> left = t;t -> height = max( height( t -> left ), height( t -> right ) ) + 1;k -> height = max( t -> height, height( t -> right ) ) + 1;t = k;}void doubleWithLeftFirst( AvlNode* &t ){left_rotate( t -> left );right_rotate( t );}void doubleWithRightFirst( AvlNode* &t ){right_rotate( t -> right );left_rotate( t );}void insert( const Type& x, AvlNode* &t ){//将新的元素插入二叉树,如果该元素值在二叉树中出现了,则什么也不做if( t == NULL ){t = new AvlNode( x, NULL, NULL );++size;}else if( x  <  t -> element ){insert( x, t -> left );if( height( t -> left ) - height( t -> right ) == 2 )if( x  <  t -> left -> element )right_rotate( t );elsedoubleWithLeftFirst( t );}else if( t -> element  <  x ){insert( x, t -> right );if( height( t -> right ) - height( t -> left ) == 2 )if( t -> right -> element  <  x )left_rotate( t );elsedoubleWithRightFirst( t );}else;//do nothingt -> height = max ( height( t -> left ), height( t -> right ) ) + 1;}void remove( const Type& x, AvlNode* &t ){//将指定元素从指定节点中移除,如果有的话if( t == NULL )return;if( x  <  t -> element ){remove( x, t -> left );if( height( t -> right ) - height( t -> left ) == 2 )if( height( t -> right -> left ) < height( t -> right -> right ) )left_rotate( t );elsedoubleWithRightFirst( t );}else if( t -> element  <  x ){remove( x, t -> right );if( height( t -> left ) - height( t -> right ) == 2 )if( height( t -> left -> right ) < height( t -> left -> left ) )right_rotate( t );elsedoubleWithLeftFirst( t );}else if( t->left != NULL  &&  t->right != NULL ){t -> element  =  findMin( t -> right ) -> element;remove( t -> element, t -> right );if( height( t -> left ) - height( t -> right ) == 2 )if( height( t -> left -> right ) < height( t -> left -> left ) )right_rotate( t );elsedoubleWithLeftFirst( t );}else{AvlNode *old = t;t = ( t -> left  !=  NULL ) ? t -> left : t -> right;delete old;--size;return;}t -> height = max( height( t -> left ), height(t -> right ) ) + 1;}bool search( const Type& x, AvlNode *t ) const {//在指定的节点中搜索指定的元素,如果有的话if( t == NULL )return false;else if( x  <  t -> element )return search( x, t -> left );else if( t -> element  <  x )return search( x, t -> right );elsereturn true;}void clear( AvlNode* &t ){//删除二叉树if( t != NULL ){clear( t -> left );clear( t -> right );delete t;}t = NULL;}void print( AvlNode* &t ) const {//对二叉树进行中序遍历,也即由小到大输出if( t == NULL )return;print( t -> left );std::cout << std::setw(5) << t -> element;print( t -> right );}AvlNode* clone( AvlNode *t ) const {//复制二叉树if( t == NULL )return NULL;return new AvlNode( t -> element, clone( t -> left ), clone( t -> right ) );}void initial(){//默认二叉树数据初始化root = NULL;size = 0;}bool initial( const Type& e ){//带指定参数的初始化root = new AvlNode( e, NULL, NULL );if( root == NULL )return false;size = 1;return true;}public:AvlTree(){//默认构造函数initial();}AvlTree( Type& e ){//带指定参数的构造函数if( !initial(e) )std::cout << "根节点构造失败!" << std::endl;}AvlTree(const AvlTree& rhs){//复制构造函数*this = rhs;}const AvlTree& operator=(const AvlTree& rhs){//复制操作符if( this != &rhs ){clear();root = clone( rhs.root );}return *this;}~AvlTree(){//析构函数clear( root );}AvlNode* findMin( AvlNode *t ){//寻找二叉树中最小数据的节点if( t != NULL )while( t -> left != NULL )t = t -> left;return t;}AvlNode* findMax( AvlNode *t ){//寻找二叉树中最大数据的节点if( t != NULL )while( t -> right  !=  NULL )t = t -> right;return t;}Type findMin(){//寻找二叉树中最小的数据AvlNode *p = findMin( root );if( p == NULL )return -1;return p -> element;}Type findMax(){//寻找二叉树中最大的数据AvlNode *p = findMax( root );if( p == NULL )return -1;return p -> element;}bool search( const Type& x ) const {//搜索指定的元素是否在二叉树中return search( x, root );}bool isEmpty() const {//判断二叉树是否为空return size == 0;}int Size(){//返回二叉树节点的数目return size;}void insert( const Type& e ){//将元素插入二叉树中insert( e, root );}void remove( const Type& e ){//将元素从二叉树中移除,如果有的话remove( e, root );}void Traverse(){//对整个二叉树进行由小到大的输出print( root );}void print_tree(){ptta.print_tree( *this );}};#endif</span>

2、printTree.h

<span style="font-family:Microsoft YaHei;">#include<string>#include<vector>#include<sstream>/*        1、专门用于打印二叉树的泛型类,使用此类需申明该类为友元、并且在使用类中定义该类的一个实例;     2、需要提供三个类型参数,第一个为结点元素的类型,第二个为结点的类型,第三个为使用类的类型;     3、最后,在调用唯一的外部接口时,需传递使用类的当前实例作为唯一的参数!*/template<typename Type, typename bten, typename ClassType>class PrintTree{int height, width;std::vector<std::string> vs;bten *root;int max(int x, int y){return x > y ? x : y;}int get_height(bten* &t){if( !t )return 0;if( t -> left == NULL  &&  t -> right == NULL )return 1;int ht = max( get_height( t -> left ), get_height( t -> right) ) + 1;return ht;}std::string transform(Type n){std::string st;std::ostringstream oss;oss << n;st = oss.str();return st;}void create_string(std::string& s, int cur_height){int i, frontw = 1, behindw = 1, pows = height - cur_height;frontw <<= pows;--frontw;behindw <<= (pows + 1);behindw -= (frontw + 1);std::string tmp;for(i = 0; i < width; ++i)tmp += " ";for(i = 0; i < frontw; ++i)s = tmp + s;for(i = 0; i < behindw; ++i)s += tmp;}void set_string(Type value, int cur_height){std::string s;if( value != -1 ){s = transform( value );int dis = width - s.size();if( dis < 0 ){std::cout << "控制宽度:" << width << '\t' << "字符串为:" << s << '\t' </span>
<span style="font-family:Microsoft YaHei;"><span style="white-space:pre"></span><< "字符串长度为:" << s.size() << std::endl;return;}for(int i = 0; i < dis; ++i)s = " " + s;}else{s = "";for(int i = 0; i < width; ++i)s = " " + s;}create_string( s, cur_height );vs[cur_height] += s;s.clear();}void push_value_map( bten* &t, int front_height ){int frh = get_cur_height( t );if( !t  &&  height > front_height ){int pows = height - front_height, level;for( level = 0; level < pows; ++level ){int count = ( !level ) ? 1 : ( 1 << level );for(int i = 0; i < count; ++i)set_string( ( Type ) -1, front_height + level + 1 );}}else if( t ){set_string( t -> element, frh );push_value_map( t -> left,  frh );push_value_map( t -> right, frh );}elsereturn;}int get_height(){return get_height( root );}int get_cur_height( bten* &t ){if( !t )return 0;int ht = 0;bten *temp = root;while( true ){if( !temp )break;if( t -> element  <  temp -> element ){temp = temp -> left;++ht;}else if(temp -> element  <   t -> element ){temp = temp -> right;++ht;}elsebreak;}return ht;}public:void print_tree( ClassType &t ){//打印二叉树的外部函数接口root = t.root;height = get_height( root );--height;std::vector<std::string> vs_tmp( height + 1 );vs = vs_tmp;std::string tm = transform( t.findMax() );width = tm.size();push_value_map( root, 0 );for(int i = 0; i < vs.size(); ++i)std::cout << vs[i] << std::endl;vs.clear();}};</span>

3、testAvlTree.cpp

<span style="font-family:Microsoft YaHei;">#include<iostream>#include "AvlTree.h"using namespace std;int main(){AvlTree<int> avlt;int x;cout<< "首次使用请先初始化根的值:";cin >> x;avlt.insert( x );cout << endl;while( 1 ){cout << "                                  二叉平衡树操作菜单" << endl;cout << "----------------------------------------------------------------------------------------\n";cout << "1---insert( &e )     2---findMin()     3---findMax()      4---search( &e )   5---empty()\n";cout << "6---remove( &e )     7---size()        8---print_tree()   0---Quit\n";cout << "----------------------------------------------------------------------------------------\n";cout << "请选择:";cin >> x;if(x <= 0  ||  x > 8)break;switch(x){case 1:cout<<"请输入要插入的值:";cin >> x;avlt.insert( x );cout<<"插入后为:"<<endl;avlt.Traverse();cout << endl;break;case 2:cout << "当前二叉树中最小的值为:" << avlt.findMin() << endl;break;case 3:cout << "当前二叉树中最大的值为:" << avlt.findMax() << endl;break;case 4:cout << "请输入待搜索的元素:";cin >> x;if( avlt.search( x ) )cout << "当前元素在二叉树中!" << endl;elsecout << "当前元素不在二叉树中!" << endl;break;case 5:if( !avlt.isEmpty() )cout << "当前二叉树不为空!" << endl;elsecout << "当前二叉树为空!" << endl;break;case 6:cout << "当前二叉树元素为:" << endl;avlt.Traverse();cout << endl;cout << "请输入要删除的元素:";cin >> x;avlt.remove( x );cout << "删除后二叉树元素为:" << endl;avlt.Traverse();cout << endl;break;case 7:cout <<"当前二叉树节点数为:" << avlt.Size() << endl;break;case 8:avlt.print_tree();break;default:break;}}return 0;}</span>


二、测试图示











可从上面的图中看出AVL树模型的变化,不管是插入还是删除元素,整个AVL树始终都保持平衡!

0 0
原创粉丝点击