zoukankan      html  css  js  c++  java
  • 数据结构(7) -- 平衡二叉树

    此版本是在数据结构(6)的基础上改造的。实现了构建平衡二叉树功能。

    //BinTree.h
    #ifndef BINTREE_H_
    #define BINTREE_H_
    #define ElemType int
    typedef struct _PNode
    {
        ElemType data;
        _PNode *left;
        _PNode *right;
        int height;
    }PNode;
    
    class BinTree
    {
    private:
        PNode *root;
    public:
        BinTree();
        ~BinTree();
        PNode* GetRoot();    //获得根节点
        void SetRoot(PNode *p) { root = p; }    //设置根节点
        PNode* Find(ElemType x , PNode *p);        //查找元素x所在位置
        PNode* FindMin(PNode *p);    //查找二叉搜索树的最小值
        PNode* FindMax(PNode *p);    //查找二叉搜索树的最大值
        PNode* Insert(ElemType x, PNode *p);  //构建二叉搜索树,所插入的元素按二叉搜索树排列
        PNode* Delete(ElemType x, PNode *p);  //删除二叉搜索树的元素    
        //遍历二叉树
        void PreOrder(PNode *p);  //先序遍历
        void CenOrder(PNode *p);  //中序遍历
        void Trave(PNode *p);     //层次遍历
        int GetHeight(PNode *p);
        PNode* AVL_Insertion(ElemType x, PNode *p);
        PNode* SingleLeftRotation(PNode *p); //左单旋
        PNode* DoubleLeftRightRotation(PNode *p); //左右双旋
        PNode* SingleRightRotation(PNode *p); //右单旋
        PNode* DoubleRightLeftRotation(PNode *p); //右左双旋
        int Max(int a, int b); //求最大值
    };
    #endif
    
    
    /////////////////////////////////////////////////////////////////////
    //BinTree.cpp
    #include "BinTree.h"
    #include <iostream>
    #include <queue>
    
    BinTree::BinTree()
    {
        root = NULL;
    }
    
    BinTree::~BinTree(){}
    
    PNode* BinTree::GetRoot()
    {
        return root;
    }
    PNode* BinTree::Find(ElemType x, PNode *p)
    {
        /*
        //尾递归实现
        if (p == NULL)
            return NULL;
        if (x > p->data)
            return Find(x, p->right);
        else if (x < p->data)
            return Find(x, p->left);
        else
            return p;*/
        while (p != NULL)
        {
            if (x > p->data)
                p = p->right;
            else if (x < p->data)
                p = p->left;
            else
                return p;
        }
        return NULL;
    }
    
    PNode* BinTree::FindMin(PNode *p)
    {
        //递归查找
        if (p == NULL)
            return NULL;
        else if (p->left == NULL)
            return p;
        else
            return FindMin(p->left);
    }
    
    PNode* BinTree::FindMax(PNode *p)
    {
        if (p != NULL)
            while (p->right != NULL)
                p = p->right;
        return p;
    }
    
    //遍历二叉树
    void BinTree::PreOrder(PNode *p)
    {
        if (p == NULL)
            return;
        std::cout << p->data << " ";
        PreOrder(p->left);
        PreOrder(p->right);
    }
    
    void BinTree::CenOrder(PNode *p)
    {
        if (p == NULL)
            return;
        CenOrder(p->left);
        std::cout << p->data << " ";
        CenOrder(p->right);
    }
    
    PNode* BinTree::Insert(ElemType x, PNode *p)
    {
        if (p == NULL)
        {
            p = new PNode();
            p->data = x;
            p->left = p->right = NULL;
        }
        else
        {
            if (x < p->data)
                p->left = Insert(x, p->left);
            else if (x > p->data)
                p->right = Insert(x, p->right);
        }
        return p;
    }
    
    PNode* BinTree::Delete(ElemType x, PNode *p)
    {
        PNode *tmp;
        if (p == NULL)
            std::cout << "要删除的元素未找到" << std::endl;
        else if (x < p->data)  //查找要删除的节点
            p->left = Delete(x, p->left);
        else if (x > p->data)
            p->right = Delete(x, p->right);
        else
        {
            //删除的元素左右节点都在,删除右子树的最小节点
            if (p->left != NULL && p->right != NULL)
            {
                tmp = FindMin(p->right);  //查找右子树的最小节点
                p->data = tmp->data;          //将右字数的最小值与当前节点的值互换    
                p->right = Delete(p->data, p->right);    //删除右字数最小节点
            }
            else
            {//删除的元素只有左节点,或只有右节点,或是叶子节点
                tmp = p;
                if (p->left == NULL)  //只有右节点,直接用右节点替换要删除节点
                    p = p->right;
                else if(p->right == NULL) //只有左节点,直接用左节点替换要删除节点
                    p = p->left;
                delete tmp;    //如果删除节点是叶子节点,直接删除当前节点
            }        
        }
        return p;
    }
    
    void BinTree::Trave(PNode *p)    //层次遍历
    {
        std::queue<PNode*> q;
        q.push(p);
        while (!q.empty())
        {
            PNode *s = q.front();
            std::cout << s->data << " ";
            if (s->left != NULL)
                q.push(s->left);
            if (s->right != NULL)
                q.push(s->right);
            q.pop();
        }
    }
    
    int BinTree::GetHeight(PNode *p)
    {
        int hl;
        int hr;
        int maxh;
        if (p)
        {
            hl = GetHeight(p->left);
            hr = GetHeight(p->right);
            maxh = (hl > hr) ? hl : hr;
            return (maxh + 1);
        }
        else
            return -1;
    }
    
    PNode* BinTree::AVL_Insertion(ElemType x, PNode *p)
    {
        //将x插入AVL树T中,并且返回调整后的AVL树
        if (p == NULL)    //如果插入空树,则新建包含一个节点的树
        {
            p = new PNode();
            p->data = x;
            p->height = 0;
            p->left = p->right = NULL;
        }
        else if (x < p->data) //插入T的左子树
        {
            p->left = AVL_Insertion(x, p->left);
            if (GetHeight(p->left) - GetHeight(p->right) == 2)
                if (x < p->left->data) //需要左旋
                    p = SingleLeftRotation(p); //左单旋
                else
                    p = DoubleLeftRightRotation(p); //左右双旋
        } //插入左子树结束
        else if (x > p->data)
        {
            p->right = AVL_Insertion(x, p->right);
            if (GetHeight(p->right) - GetHeight(p->left) == 2)
                if (x > p->right->data) //需要又旋
                    p = SingleRightRotation(p); //右单旋
                else
                    p = DoubleRightLeftRotation(p); //右左双旋
        }
        //x == p->data无需插入
        p->height = Max(GetHeight(p->left), GetHeight(p->right)) + 1;
        return p;
    }
    
    int BinTree::Max(int a, int b)
    {
        return (a > b ? a : b);
    }
    
    PNode* BinTree::SingleLeftRotation(PNode *A) //左单旋
    {
        //注意,A必须有一个左子结点
        PNode *B = A->left;
        A->left = B->right;
        B->right = A;
        A->height = Max(GetHeight(A->left), GetHeight(A->right)) + 1;
        B->height = Max(GetHeight(B->left), GetHeight(A->right)) + 1;
        return B;
    }
    
    PNode* BinTree::DoubleLeftRightRotation(PNode *A) //左右双旋
    {
        A->left = SingleRightRotation(A->left);
        return SingleLeftRotation(A);
    }
    
    PNode* BinTree::SingleRightRotation(PNode *A) //右单旋
    {
        PNode *B = A->right;
        A->right = B->left;
        B->left = A;
        A->height = Max(GetHeight(A->left), GetHeight(A->right)) + 1;
        B->height = Max(GetHeight(B->left), GetHeight(A->right)) + 1;
        return B;
    }
    
    PNode* BinTree::DoubleRightLeftRotation(PNode *A) //右左双旋
    {
        A->right = SingleLeftRotation(A->right);
        return SingleRightRotation(A);
    }
    
    
    ////////////////////////////////////////////////////////
    //测试
    #include <iostream>
    #include "BinTree.h"
    using namespace std;
    
    int main()
    {
        BinTree bt;
        //构造二分查找树
        bt.SetRoot(bt.AVL_Insertion(2, bt.GetRoot())); //注意跟新根节点    
        bt.SetRoot(bt.AVL_Insertion(3, bt.GetRoot()));
        bt.SetRoot(bt.AVL_Insertion(4, bt.GetRoot()));
        bt.SetRoot(bt.AVL_Insertion(5, bt.GetRoot()));
        bt.SetRoot(bt.AVL_Insertion(6, bt.GetRoot()));
        bt.SetRoot(bt.AVL_Insertion(8, bt.GetRoot()));
        bt.SetRoot(bt.AVL_Insertion(2, bt.GetRoot()));
        bt.SetRoot(bt.AVL_Insertion(1, bt.GetRoot()));
        cout << bt.GetHeight(bt.GetRoot()) << endl;
    
        cout << "先序遍历: " << endl;
        bt.PreOrder(bt.GetRoot());
        cout << endl;
        cout << "中序遍历: " << endl;
        bt.CenOrder(bt.GetRoot());
        cout << endl;
        cout << "层次遍历:" << endl;
         bt.Trave(bt.GetRoot());
        cout << endl;
        cout << "最小值:" << bt.FindMin(bt.GetRoot())->data << endl;
        cout << "最大值:" << bt.FindMax(bt.GetRoot())->data << endl;
        ///////////////////////////////////////////////////////////////////
        //cout << endl << "删除节点 5 " << endl;
        //bt.Delete(4, bt.GetRoot());
        cout << "先序遍历: " << endl;
        bt.PreOrder(bt.GetRoot());
        cout << endl;
        cout << "中序遍历: " << endl;
        bt.CenOrder(bt.GetRoot());
        cout << endl;
        cout << "层次遍历:" << endl;
        bt.Trave(bt.GetRoot());
        cout << endl;
        cout << "最小值:" << bt.FindMin(bt.GetRoot())->data << endl;
        cout << "最大值:" << bt.FindMax(bt.GetRoot())->data << endl;
        system("pause");
        return 0;
    }
  • 相关阅读:
    Java 8 新特性之 Stream&forEach&map&filter&limit&sorted&统计函数&Collectors&并行(parallel)程序(转)
    kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
    java8 stream API
    Docker容器CPU、memory资源限制
    JVM调优总结 -Xms -Xmx -Xmn -Xss
    JAVA8之妙用Optional解决判断Null为空的问题
    【王凤鸣 太极缠丝功笔记】第二章
    【精美凉菜】黄瓜腐竹花生豆
    【瓜果篇】黄瓜
    【Teradata UDF】中文按字符查找chs_instr
  • 原文地址:https://www.cnblogs.com/yongssu/p/4402274.html
Copyright © 2011-2022 走看看