zoukankan      html  css  js  c++  java
  • BinTreeSearch And AVL

    一.平衡二叉树 VS 搜扫二叉树

     1. 平衡二叉树:解决在树的结构搜扫的时候,防止搜扫数据呈现出斜二叉树的数据结构,因此在节点插入和删除的时候,自动的调节树的数据结构,让树搜索速度达到log(N)的时间复杂度。

    下面二叉搜索树的构造和其各种运用Delete,Insert

    对于二叉搜索树删除:1.度为2节点删除,要么从左子树选择最大节点代替此删除节点,或者从右子树中选择最小的节点代替此节点。2.度不大于1的节点:将左节点或者右节点覆盖此为位置T=T->Left。

    #include<iostream>
    using namespace std;
    #define  ElementType int
    //对二叉搜扫树各种功能模拟
    
    typedef struct TreeNode{
        ElementType Data;
        struct TreeNode *LeftNode;
        struct TreeNode *RightNode;
    }*BinTree,BinTreeNode;
    
    BinTree CreateBinSearch()
    {
        BinTree root=new BinTreeNode,ptr,Rear;
        root->LeftNode=NULL;root->RightNode=NULL;root->Data=NULL;
        int num=100;
        cout<<"输出-1值表示停止"<<endl;
        
        
        while(true)
        {
            cin>>num;
            ptr=root;
            if(num==-1)  break;
            if(ptr->Data==NULL)
            {
                ptr->Data=num;//空树
            }
            else
            {
                Rear=new BinTreeNode;
                Rear->Data=num;Rear->LeftNode=NULL;Rear->RightNode=NULL;
    
                while(ptr)
                {
                    if(num<ptr->Data)
                    {
                        if(ptr->LeftNode==NULL)
                        {    ptr->LeftNode=Rear; break;}
                        else
                                 ptr=ptr->RightNode;
                    }
                    else{
                        if (ptr->RightNode==NULL)
                            
                        {
                            {ptr->RightNode=Rear;break;}
                        }else
                        {
                            ptr=ptr->RightNode;
                        }
                    
                    }            
            
                }
    
            }
        }
    
        return root;
    }
    BinTree Insert(BinTree Rear,int X)
    {
        //采用递归的形式对新输入的值进行插入,不断对值递归调用直到最后进行
        
        if(!Rear) 
        {        //最后递归找到插入位置最后对位置进行插入
                cout<<"这个是一颗空树"<<endl;
                Rear->Data=X;Rear->LeftNode=NULL;Rear->RightNode=NULL;
        }
        //使用尾部递归方式
        else{
                    if(Rear->Data>X)
                        Insert(Rear->LeftNode,X);
                    else
                        Insert(Rear->RightNode,X);
    
        }
        return Rear;
    
    }
    BinTree FindMin(BinTree Rear)
    {
        /*while(Rear->LeftNode)
            Rear=Rear->LeftNode;
        return Rear;*/
        //采用递归的话
        if(!Rear) return NULL;
        else if(!Rear->LeftNode)
            return Rear;
        else
            FindMin(Rear->LeftNode);
    }
    BinTree Delete(BinTree Rear,int delete_value)
    {
        //对于删除节点分为两种情况,节点度=2,只能从此节点的左子树中找一个最大值代替此删除点
        //度=1,删除此点,将其单个子节点填补其位置就行
    
        if(!Rear)
            cout<<"删除的点没有找到"<<endl ;
        //开始寻找要删除点->Data=delete_value;
        if(delete_value>Rear->Data)
            Delete(Rear->RightNode,delete_value);
        else if(Rear->Data<delete_value)
            Delete(Rear->LeftNode,delete_value);
        else
        {
            //刚好找到其位置
            BinTree tmp;
            if(Rear->LeftNode && Rear->RightNode)
            {
                tmp=FindMin(Rear->RightNode);
                Rear->Data=tmp->Data;
                //在从右子树中删除最小的节点,是一个叶子节点
                Delete(Rear->RightNode,tmp->Data);
            }
            else{
                //最多只有一个节点
                if(Rear->LeftNode)
                    Rear=Rear->LeftNode;
                else
                    Rear=Rear->RightNode;
            }
        }
    }
    int main()
    {
        BinTree rootNode;
        rootNode=CreateBinSearch();
        cout<<"********向二叉搜扫树中插入值************"<<endl;
        int Insert_numbel;
        cin>>Insert_numbel;
        rootNode=Insert(rootNode,Insert_numbel);
    
        cout<<"********向二叉搜扫树中删除值************"<<endl;
        int Y;
        cin>>Y;
        Delete(rootNode,Y);
        return 0;
    }

    2. 在调节树的数据结构的,通过平衡因子BF调节其结构;BF=h(x-Right)-h(x-left)---节点X的右子树高度减去左子树高度

    3.根据插入和删除的节点不同,将造成不平衡节点分为4种方式,LL,RR,LR,RL 四种格式

     规则:调整之后必须要保持其是二叉搜索树的特性

    LL: 由于B节点左子树插入节点导致A点失去平衡:以B节点为轴心,A节点顺时针循转到B的右子树中,B原来的右子树变为A的左子树

     

    LR:B节点右子插入新的节点导致A节点失去平衡,插入在被破坏者May的左子树的右子树上,因此做LR循转

    Mar调整到根节点上,A-B-C:调整为C-B-A。C是B的右子树节点。

     判断其是单旋 Vs双旋  插入B节点的后面

    比较 破坏者C,被破坏者A,A>B>C(A<B<C):A的左子树左子树上LL(右子树右子树RR);

    如果C节点在中间A>C>B(A<C<B): 做双旋转,A的左子树右子树上LR旋转(A 的右子树左子树上RL旋转)。

    #include<iostream>
    #include<queue>
    using namespace std;
    
    #define  ElementType int
    
    typedef struct AVLTree{
        ElementType Data;
        int Height;//计算单个节点上的树的高度
        AVLTree  *LeftNode;
        AVLTree *RightNode;
        //构造函数初始化
        AVLTree():Data( NULL),Height(NULL),LeftNode(NULL),RightNode(NULL){}
    }*AvlTree,AvlTreeNode;
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    int GetHeight(AvlTree T)
    {
        if (!T)
            return -1;
        else
            return T->Height;
    
        if (!T)
            return 0;
        else
            return max(GetHeight(T->LeftNode),GetHeight(T->RightNode))+1;
    
    }
    AvlTree SigngleRoatedWithLeft(AvlTree T)
    {
        //左单旋
        AvlTree T1;
        T1=T->LeftNode;
        T->LeftNode=T1->RightNode;
        T1->RightNode=T;
        //更新新的矩阵值,高的指树的高度
        T->Height=max(GetHeight(T->LeftNode),GetHeight(T->RightNode))+1;
        T1->Height=max(GetHeight(T1->LeftNode),T->Height)+1;
        return T1;
    
    }
    
    AvlTree SigngleRoatedWithRight(AvlTree T)
    {//右单旋
        AvlTree T1;
        T1=T->RightNode;
        T->RightNode=T1->LeftNode;
        T1->LeftNode=T;
        //更新新的矩阵值,高的指树的高度
        T->Height=max(GetHeight(T->LeftNode),GetHeight(T->RightNode))+1;
        T1->Height=max(GetHeight(T1->LeftNode),T->Height)+1;
        return T1;
    
    }
    AvlTree DoubleRoatedLeftandRight(AvlTree A)
    {
        //双旋,左右双旋,先做右旋修改A->left
        //A 节点右一个左节点B,B有一个右节点C
        A->LeftNode=SigngleRoatedWithRight(A->LeftNode);
        //对A做左旋
        return  SigngleRoatedWithLeft(A);
    
    
    }
    AvlTree DoubleRoatedRightandLeft(AvlTree A)
    {
        //双旋,左右双旋,先做右旋修改A->left
        //A 节点右一个左节点B,B有一个右节点C
        //对A-.right做左旋
        A->RightNode=SigngleRoatedWithLeft(A->RightNode);
        //对A做左旋
        return  SigngleRoatedWithRight(A);
    
    
    }
    
    
    AvlTree Insert(ElementType X,AvlTree T)
    {
        if(!T)//判断其是否是空树
        {//t通过递归建立树
            T=new AvlTreeNode;
            T->Data=X;
            T->Height=0;
    
        }
        else if(X<T->Data)
        {
            /*插入到左子树中*/
            T->LeftNode=Insert(X,T->LeftNode);
            if(GetHeight(T->LeftNode)-GetHeight(T->RightNode)==2)
            {        
                if(X<T->LeftNode->Data)
                        {
                            T=SigngleRoatedWithLeft(T);//左单旋
                          }
                    else{
                            T=DoubleRoatedLeftandRight(T);//左右单旋
                            }
                    }
            }
        else if(X>T->Data)
        {
            T->RightNode=Insert(X,T->RightNode);
            if(GetHeight(T->LeftNode)-GetHeight(T->RightNode)==-2)
            {
                if(X>T->RightNode->Data)
                {
                    T=SigngleRoatedWithRight(T);//左单旋
                }
                else
                {
                    //右左双旋
                    T=DoubleRoatedRightandLeft(T);
                }
            }
        }
    
        T->Height=max(GetHeight(T->LeftNode),GetHeight(T->RightNode))+1;
        return T;
    }
    void Pre_order(AvlTree T)
    {
        if(T)
        {
            cout<<T->Data<<"  ";
            Pre_order(T->LeftNode);
            Pre_order(T->RightNode);
        
        }
        else
        {
            cout<<"#"<<"  ";
        }
    
    }
    void Level_order(AvlTree T)
    {//使用队列对层次遍历
        queue<AvlTree>Q;
        Q.push(T);
        while(T && !Q.empty())
        {
            T=Q.front();
            cout<<T->Data<<" ";
            if(T->LeftNode) Q.push(T->LeftNode);
            if(T->RightNode) Q.push(T->RightNode);
            Q.pop();
        }
    }
    int main()
    {
        AvlTree Avl=new AvlTreeNode;
        
        //通过插入建立AVL平衡树,通过斜插;
        for(int i=1;i<=7;i++)
        {
            Avl=Insert(i,Avl);
        }
        //前序遍历输出
         Pre_order(Avl);
         cout<<endl;
         cout<<"层次遍历"<<endl;
         Level_order(Avl);
        return 0;
    }

    二叉平衡树采用java中泛型数据,其中加入对数据的remove处理

    package Tree;
    
    import java.util.LinkedList;
    
    //12.1采用数据进行测试
    
    
    
    public class AVLTree <AnyType> {
        
        private static class AvlNode<AnyType>
        {
                AnyType element;
                AvlNode<AnyType> left;
                AvlNode<AnyType>right;
                int height;//AvlTree Hegiht
                
             
                public AvlNode(AnyType E)
                {
                    this.element=E;
                    this.left=null;
                    this.right=null;
                    this.height=-1;
                }
                public AvlNode(AnyType thiselement,AvlNode<AnyType>lt,AvlNode<AnyType>rt,int h)
                {
                    this.element=thiselement;
                    this.left=lt;
                    this.right=rt;
                    this.height=h;
                }
        }
        public static AvlNode  Avltree;
        
        //通过插入AVlTree
        private AvlNode<AnyType> insert(AnyType x,AvlNode<AnyType>t)
        {
            if(t==null)
                return new AvlNode(x);
            int compareResult=((Comparable<AnyType>) x).compareTo(t.element);
            
            if(compareResult>0)
                t.right=insert(x,t.right);
            else if(compareResult<=0)
                    t.left=insert(x,t.left);
            //最后对插入树进行调整,通过遍历其中每个树的高度
            return balance(t);
    }
        private int height(AvlNode<AnyType>p)
        {
            return p==null?-1:p.height;
        }
        private AvlNode<AnyType>roatedWithLeftChild(AvlNode <AnyType>k2)
        {
            //k2 平衡性被破坏的点
            AvlNode<AnyType> k1=k2.left;
            k2.left=k1.right;
            k1.right=k2;
            
            //更新所在的的高度,k1上升,k2下降
            k2.height=Math.max(height(k2.left),height(k2.right))+1;
            k1.height=Math.max(height(k1.left),k2.height)+1;
            return k1;
        }
        private AvlNode<AnyType>roatedWithRightChild(AvlNode <AnyType>k2)
        {
            //k2 平衡性被破坏的点
            AvlNode<AnyType> k1=k2.right;
            k2.right=k1.left;
            k1.left=k2;
            
            //更新所在的的高度,k1上升,k2下降
            k2.height=Math.max(height(k2.left),height(k2.right))+1;
            k1.height=Math.max(height(k1.right),k2.height)+1;
            return k1;
        }
        
        private AvlNode<AnyType>doubleWithLeftChild(AvlNode<AnyType>k3)
        {
            k3.left=roatedWithRightChild(k3.left);
            return roatedWithLeftChild(k3);
        }
        private AvlNode<AnyType>doubleWithRightChild(AvlNode<AnyType>k3)
        {
            k3.right=roatedWithLeftChild(k3.right);
            return roatedWithRightChild(k3);
        }
        
        private AvlNode<AnyType > balance (AvlNode<AnyType> t)
        {
            if(t==null)
                return t;
            
            if(height(t.left)-height(t.right)>1)
            {
                if(height(t.left.left)>=height(t.left.right))
                    //这里等于号,说明t的左树左子孙 =左子树的右子孙;这样树调整只需要进行单步的旋转就可以解决问题
                    t=roatedWithLeftChild(t);
                else
                    t=doubleWithLeftChild(t);
            }
            else
            {
                if(height(t.right)-height(t.left)>1)
                    if(height(t.right.right)>=height(t.right.left))
                        t=roatedWithRightChild(t);
                    else
                        t=doubleWithRightChild(t);
            }
            t.height=Math.max(height(t.left),height(t.right))+1;
            return t;
        }
        
        //数据点删除
        private AvlNode<AnyType> findMin(AvlNode<AnyType>t)
        {
            if(t==null)
                return null;
            if(t.left==null)
                return t;
            return findMin(t.left);
        }
        private AvlNode <AnyType> remove (AnyType x,AvlNode <AnyType>t)
        {  boolean flag=false;
            if(t==null)
                return null;
            @SuppressWarnings("unchecked")
            int compareResult=((Comparable<AnyType>) x).compareTo(t.element);
            AvlNode <AnyType> tmp=null;
            if(compareResult<0)
            {
                remove(x,t.left);
            }
            else if(compareResult>0)
                {  remove(x,t.right);}
            else
            {//刚好找到其位置
                flag=true;
                if(t.left!=null && t.right!=null)
                {    
                     tmp=findMin(t.right);
                     t.element=tmp.element;
                     t.right=remove(tmp.element,t.right);
                }
                else
                {
                    //度是1
                    if(t.left!=null)
                        t=t.left;
                    else
                        t=t.right;
                                        
                }
                
            }
            System.out.println("Flag: "+flag);
            return balance(t);
        }
        public static void PreOrder(AvlNode P)
        {
            if(P!=null)
            {
                System.out.print("["+P.element+"]");
                PreOrder(P.left);
                PreOrder(P.right);
            }
        }
        public static void leveOrder (AvlNode P)
        {
            //使用层次遍历,使用队列
            LinkedList <AvlNode>queue=new LinkedList<AvlNode>();
            queue.add(P);
            while((P!=null) &&(!queue.isEmpty()))
            {
                P=queue.element();
                System.out.print("["+P.element+"]");
                if(P.left!=null) queue.add(P.left);
                if(P.right!=null) queue.add(P.right);
                queue.remove();
            }
            
        }
        public static void main(String [] args)
        {
            System.out.println("通过insert方法建立AVLTree");
            int [] Data={ 1,2,3,4,5,6,7,8};
            AVLTree Tree=new AVLTree();
            for(int i=0;i<Data.length;i++)
            {
                Tree.Avltree=Tree.insert(Data[i],Tree.Avltree);
                
            }
            
            System.out.println("Tree.Avltree Preorder *******:");
            PreOrder(Tree.Avltree);
            System.out.println("Tree.Avltree Leveorder *******:");
            leveOrder(Tree.Avltree);
            System.out.println("Tree.Avltree remove *******:");
            Tree.remove(6, Tree.Avltree);
            leveOrder(Tree.Avltree);
            
        }
        }

    结果:

    通过insert方法建立AVLTree

    Tree.Avltree Preorder *******:
    [4][2][1][3][6][5][7][8]
    Tree.Avltree Leveorder *******:
    [4][2][6][1][3][5][7][8]
    Tree.Avltree remove *******:
    Flag: true
    Flag: true
    Flag: false

    [4][2][7][1][3][5][8]

  • 相关阅读:
    JS编码解码详解
    web的几种返回顶部
    图片的懒加载的两种效果
    获取两个日期差
    C#虚方法
    依赖注入(DI)和Ninject
    在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的
    PetShop的系统架构设计
    C#综合揭秘——细说多线程(下)
    C# Socket编程(4)初识Socket和数据流
  • 原文地址:https://www.cnblogs.com/woainifanfan/p/6034791.html
Copyright © 2011-2022 走看看