zoukankan      html  css  js  c++  java
  • VC++2012编程演练数据结构《9》平衡二叉搜索树

    平衡二叉搜索树

      任何结点的左子树和右子树高度最多相差1的二叉搜索树。
      (1)AVL树的插入算法
      a. 插入结点之后仍然是AVL树,则不调整;
      b. 插入结点之后不再满足AVL树条件,则进行调整,根据导致不平衡的原因,分为:
      a) LL型――单旋转调整
      b) LR型――双旋转调整
      c) RL型――双旋转调整
      d) RR型――单旋转调整
      下图是顺序插入单词{cup,cop,copy,hit,hi,his,hia}后得到的AVL树,单词之间按照字典顺序比较:
      (2)AVL树的删除算法
      a. 删除过程如BST结点的删除算法

      b. 删除后调整――从被删除的结点找到祖父结点,然后开始单旋转或多旋转操作,一次旋转结束并不 意味着树已经平衡,因为这可能会导致它的祖先结点发生新的不平衡。所以这样的调整操作要一直进行下去,直到树平衡为止。

    类的实现如下

    //平衡二叉搜索树类定义与实现
    template<class T> class BSTree;
    //平衡二叉搜索树的结点类型定义
    template<class T> struct TNode
    {private:
    TNode<T>  *left;//左子树指针
    TNode<T> *right;//右子树指针
    public:
    	int balance;//平衡因子
    	T data;//数据域
    	friend class BSTree<T>;
    	//构造函数
    	TNode():left(NULL),right(NULL),balance(0){ }
    	TNode(T item,TNode<T> *left1,TNode<T> *right1)
    		:balance(0),data(item),left(left1),right(right1){ }
    };
    template<class T> class BSTree
    {private:
    int size;
    public:
    	//构造函数
    	BSTree(TNode<T> *&root):size(0){root=NULL;}
    	//被ClearBST()所调用的函数
    	void DeleteTree(TNode<T> *&root);
    	//LL型调整操作
    	void LL(TNode<T> **a,TNode<T> **b);
    	//RR型调整操作
    	void RR(TNode<T> **a,TNode<T> **b);
    	//LR型调整操作
    	void LR(TNode<T> **a,TNode<T> **b);
    	//RL型调整操作
    	void RL(TNode<T> **a,TNode<T> **b);
    	//释放空间
    	void FreeBST(TNode<T> *&root);
    	//求平衡二叉搜索树中所有结点数
    	int BSTSize();
    	//判断平衡二叉搜索树是否为空
    	int BSTEmpty(TNode<T> *&root);
    	//取根指针
    	TNode<T> *GetRoot(TNode<T> *&root);
    	//从平衡二叉搜索树中查找元素
    	TNode<T> *BSTLocate(TNode<T> *&root,T item);
    	//向平衡二叉搜索树中插入元素
    	void BSTInsert(TNode<T> *&root,T item);
    	//中序遍历平衡二叉搜索树中的所有结点
    	void Inorder(TNode<T> *&root);
    	//求平衡二叉搜索树的深度
    	int BSTreeDepth(TNode<T> *&root);
    	//求平衡二叉搜索树中所有结点数
    	int BSTreeCount(TNode<T> *&root);
    	//求平衡二叉搜索树中所有叶子结点数
    	int BSTreeLeafCount(TNode<T> *&root);
    	//清除平衡二叉搜索树,使之变为一棵空树
    	void ClearBST(TNode<T> *&root);
    	//初始化平衡二叉搜索树
    	void SetTNode(TNode<T> *&root,T item);
    	//获取设置的平衡二叉搜索树的一个结点
    	TNode<T> *GetTNode(T item,TNode<T> *left,TNode<T> *right);
    };
    //平衡二叉搜索树的类实现
    template<class T>
    void BSTree<T>::DeleteTree(TNode<T> *&root)
    {if(root==NULL) return;
    if(root->left!=NULL)
    DeleteTree(root->left);
    if(root->right!=NULL)
    DeleteTree(root->right);
    free(root);
    }
    template<class T>
    void BSTree<T>::LL(TNode<T> **a,TNode<T> **b)
    {(*a)->balance=0;
    (*a)->left=(*b)->right;
    (*b)->balance=0;
    (*b)->right=(*a);
    }
    template<class T>
    void BSTree<T>::RR(TNode<T> **a,TNode<T> **b)
    {(*a)->balance=0;
    (*a)->right=(*b)->left;
    (*b)->balance=0;
    (*b)->left=(*a);
    }
    template<class T>
    void BSTree<T>::LR(TNode<T> **a,TNode<T> **b)
    {TNode<T> *c;
    c=(*b)->right;//c是插入结点
    (*a)->left=c->right;
    (*b)->right=c->left;
    c->left=(*b);
    c->right=(*a);
    switch(c->balance)
    {case 0:(*a)->balance=0;
    (*b)->balance=0;
    break;
    case 1:(*a)->balance=-1;//插入的结点在c的左子树
    	(*b)->balance=0;
    	break;
    case -1:(*a)->balance=0;//插入的结点在c的右子树
    	(*b)->balance=1;
    	break;}
    c->balance=0;
    (*b)=c;//使b指向调整后的子树的根
    }
    template<class T>
    void BSTree<T>::RL(TNode<T> **a,TNode<T> **b)
    {TNode<T> *c;
    c=(*b)->left; //c是插入结点
    (*a)->right=c->left;
    (*b)->left=c->right;
    c->right=(*b);
    c->left=(*a);
    switch(c->balance)
    {case 0:(*a)->balance=0;
    (*b)->balance=0;
    break;
    case 1:(*a)->balance=0;//插入的结点在c的左子树
    	(*b)->balance=-1;
    	break;
    case -1:(*a)->balance=1;//插入的结点在c的右子树
    	(*b)->balance=0;
    	break;}
    c->balance=0;
    (*b)=c;//使b指向调整后的子树的根
    }
    template<class T>
    void BSTree<T>::FreeBST(TNode<T> *&root)
    {DeleteTree(root);}
    template<class T>
    int BSTree<T>::BSTSize()
    {return(size);}
    template<class T>
    int BSTree<T>::BSTEmpty(TNode<T> *&root)
    {if(root==NULL) return(1);
    else return(0);}
    template<class T>
    TNode<T> *BSTree<T>::GetRoot(TNode<T> *&root)
    {return(root);}
    template<class T>
    TNode<T> *BSTree<T>::BSTLocate(TNode<T> *&root,T item)
    {TNode<T> *t;
    t=root;
    while(t!=NULL)
    {if(item==t->data) break;
    else
    if(item<t->data) t=t->left;
    else t=t->right;}
    return(t);
    }
    template<class T>
    void BSTree<T>::BSTInsert(TNode<T> *&root,T item)
    {TNode<T> *t,*p,*newN,*a,*b,*f;
    newN=new TNode<T>;
    newN->data=item;
    if(root==NULL)
    {root=newN;
    size++;
    return;}
    t=root;p=NULL;
    a=t;f=p;
    while(t!=NULL)
    {if(t->balance!=0)
    {a=t;f=p;}
    p=t;
    if(item<t->data) t=t->left;
    else t=t->right;}
    if(item<p->data) p->left=newN;
    else p->right=newN;
    size++;
    if(item<a->data)
    {b=t=a->left;}
    else {b=t=a->right;}
    while(t!=NULL&&t->data!=item)
    {if(item<t->data)
    {t->balance=1;
    t=t->left;}
    else {t->balance=-1;t=t->right;}}
    if(a->balance==0)
    {if(item<a->data) a->balance=1;
    else a->balance=-1;
    return;}
    else
    if(item<a->data&&a->balance==-1||
       item>a->data&&a->balance==1)
    {a->balance=0;return;}
    else
    {if(a->balance==1)
    if(b->balance==1)
    LL(&a,&b);
    else LR(&a,&b);
    else
    if(b->balance==-1) RR(&a,&b);
    else RL(&a,&b);}
    if(f==NULL) root=b;
    else
    {if(f->left==a) f->left=b;
    else f->right=b;}
    }
    template<class T>
    void BSTree<T>::Inorder(TNode<T> *&root)
    {if(root!=NULL) {
    	Inorder(root->left);
    	cout<<setw(2)<<root->data;
    	Inorder(root->right);}
    }
    template<class T>
    int BSTree<T>::BSTreeDepth(TNode<T> *&root)
    {if(root==NULL) return 0;
    else
    {  //计算左子树的深度
    	int dep1=BSTreeDepth(root->left);
    	//计算右子树的深度
    	int dep2=BSTreeDepth(root->right);
    	//返回树的深度
    	if(dep1>dep2) return dep1+1;
    	else return dep2+1;}
    }
    template<class T>
    int BSTree<T>::BSTreeCount(TNode<T> *&root)
    {if(root==NULL) return 0;
    else 
    return BSTreeCount(root->left)+BSTreeCount(root->right)+1;
    }
    template<class T>
    int BSTree<T>::BSTreeLeafCount(TNode<T> *&root)
    {if(root==NULL) return 0;
    else
    if(root->left==NULL && root->right==NULL) return 1;
    else
    return BSTreeLeafCount(root->left)+BSTreeLeafCount(root->right);
    }
    template<class T>
    void BSTree<T>::ClearBST(TNode<T> *&root)
    {DeleteTree(root);
    root=NULL;
    size=0;
    }
    template<class T>
    void BSTree<T>::SetTNode(TNode<T> *&root,T item)
    {root->data=item;
    root->balance=0;
    root->left=NULL;
    root->right=NULL;
    }
    template<class T>
    TNode<T>* BSTree<T>::GetTNode(T item,TNode<T> *left,TNode<T> *right)
    {TNode<T> *ptr;
    ptr=new TNode<T>;
    ptr->data=item;
    ptr->balance=0;
    ptr->left=left;
    ptr->right=right;
    return(ptr);
    }



    调用如下

    #include<conio.h>
    #include<stdlib.h>
    #include "AVLTREE.h"
    using namespace std;
    TNode<char> *q;
    void main()
    {cout<<"运行结果:\n";
    int i;
    char test[50]="abxyMNcdefgqwertyuizxcvbnm";
    BSTree<char> t(q);
    //cout<<"input data:\n";
    //gets(test);
    for(i=0;test[i]!='\0';i++)
    t.BSTInsert(q,test[i]);
    cout<<"平衡二叉搜索树的结点数="<<t.BSTSize()<<endl;
    cout<<"平衡二叉搜索树的结点数="<<t.BSTreeCount(q)<<endl;
    cout<<"平衡二叉搜索树的深度="<<t.BSTreeDepth(q)<<endl;
    cout<<"平衡二叉搜索树的叶子结点数="<<t.BSTreeLeafCount(q)<<endl;
    cout<<"中序遍历平衡二叉搜索树:\n";
    t.Inorder(q);
    getch();
    t.FreeBST(q);
    }
    



    效果如下



    代码下载如下

    http://download.csdn.net/detail/yincheng01/4785937


  • 相关阅读:
    怎样才能让您的网站看起来很专业 ?
    JavaScript slice() 方法
    Jquery日历控件
    100w数据,查询只要1秒(转)
    我的WCF之旅(1):创建一个简单的WCF程序(转载)
    名企面试官精讲典型编程题之C#篇(转自CSDN)
    day01
    Delphi初浅入门笔记之十二:多媒体编程五(绘制文字篇)
    Delphi初浅入门笔记之四:过程与函数(函数篇)
    Delphi初浅入门笔记之三:过程和函数(过程篇)
  • 原文地址:https://www.cnblogs.com/new0801/p/6177657.html
Copyright © 2011-2022 走看看