zoukankan      html  css  js  c++  java
  • 二叉查找树

    特征

    1.左子树上所有结点的值均小于或等于它的根结点的值

    2.右子树上所有结点的值均大于或等于它的根结点的值。

    3.左、右子树也分别为二叉排序树。

    如下就是一棵典型的二叉查找树

    因为查找使用二分查找法,所以查询时间复杂度是 O(lg2)

    操作

    二叉树的操作也就是增删查、遍历

    查找就是二分查找。增添节点和删除节点的时候,要保持二叉树的性质。

    遍历分为前序遍历(preorder travel)、中序遍历(inorder travel)、后续遍历(postorder travel)

    前序遍历就是根节点第一个被遍历,按照“中左右”顺序,子树也按照这个顺序。中序按照“左中右”顺序。后续按照“左右中”顺序。

    可以看到,前序就是根节点第一个被遍历,中序就是根节点在中间被遍历,后续就是根节点最后被遍历。都是针对根节点的。

    通过前序+中序、后序+中序 可以还原一棵树。

    比如上面这棵树,前序遍历:3102645,中序遍历:0123465

    通过前序可以看到3是根节点,再看中序,3前面的 012 就是左子树,3后面的 456 就是右子树。继续看前序,1是左子树的根节点,6是右子树的根节点...依次类推,递归下去。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    #include <stack>
    #include <list>
    #include <queue>
    #include <iostream>
    
    enum EColor
    {
        WHITE = 0,
        BLACK,
    };
    
    template <typename T>
    struct stTreeNode
    {
        T d;
        int color;
        struct stTreeNode *left, *right;
    
        stTreeNode(T data):d(data),color(WHITE),left(NULL),right(NULL) {}
    };
    
    template <typename T>
    class CTree
    {
    public:
        typedef T               value_type;
        typedef T&              reference;
        typedef T*              pointer;
        typedef stTreeNode<T>   node_type;
        typedef node_type*      node_pointer;
    
        CTree():root(NULL){}
        CTree(const pointer arr, int len);
    
        void            insert(value_type data);
        void            del(value_type data);
        node_pointer    find(value_type data);
        bool            empty() {return root == NULL;};
    
        int             height();
    
        void            preorderTravel();
        void            inorderTravel();
        void            postorderTravel();
        void            layerTravle();
    
    private:
        node_pointer root;
    
        void            _insert(node_pointer *root, value_type data);
        int             _height(node_pointer root);
    };
    
    template <typename T>
    CTree<T>::CTree(const CTree<T>::pointer arr, int len)
    {
        root = NULL;
        for (int i = 0; i < len; ++i)
        {
            _insert(&root, arr[i]);
        }
    }
    
    template <typename T>
    void CTree<T>::_insert(CTree<T>::node_pointer *root, CTree<T>::value_type data)
    {
        if (*root == NULL)
        {
            *root = new CTree<T>::node_type(data);
        }
        else if (data > (*root)->d)
        {
            _insert(&(*root)->right, data);
        }
        else
        {
            _insert(&(*root)->left, data);
        }
    }
    
    template <typename T>
    void CTree<T>::insert(CTree<T>::value_type data)
    {
        _insert(&this->root, data);
    }
    
    template <typename T>
    typename CTree<T>::node_pointer CTree<T>::find(CTree<T>::value_type data)
    {
        CTree<T>::node_pointer tmp = root;
        while (tmp != NULL)
        {
            if (tmp->d == data)
            {
                return tmp;
            }
            else if (data > tmp->d)
            {
                tmp = tmp->right;
            }
            else
            {
                tmp = tmp->left;
            }
        }
        return tmp;
    }
    
    template <typename T>
    void CTree<T>::del(CTree<T>::value_type data)
    {
        CTree<T>::node_pointer parent = root;
        CTree<T>::node_pointer tmp = root;
        int left = -1;
    
        while (tmp != NULL && tmp->d != data)
        {
            parent = tmp;
            if (data > tmp->d)
            {
                tmp = tmp->right;
                left = 0;
            }
            else
            {
                tmp = tmp->left;
                left = 1;
            }
        }
    
        if (!tmp)
        {
            return;
        }
    
        // 要删除的节点没有左子树
        if (!tmp->left)
        {
            if (left)
            {
                parent->left = tmp->right;
            }
            else
            {
                parent->right = tmp->right;
            }
        }
        else
        {
            CTree<T>::node_pointer cur = tmp;
            parent = tmp;
            tmp = tmp->left;
            while (tmp->right != NULL)
            {
                parent = tmp;
                tmp = tmp->right;
            }
            cur->d = tmp->d;
            if (parent->left == tmp)
            {
                parent->left = tmp->left;
            }
            else
            {
                parent->right = tmp->left;
            }
            delete tmp;
        }
    }
    
    template <typename T>
    void CTree<T>::preorderTravel()
    {
        std::stack<CTree<T>::node_pointer, std::list<CTree<T>::node_pointer> > S;
        if (root)
        {
            S.push(root);
        }
    
        while (!S.empty())
        {
            CTree<T>::node_pointer node = S.top();
            std::cout << node->d << " ";
            S.pop();
            if (node->right)
            {
                S.push(node->right);
            }
            if (node->left)
            {
                S.push(node->left);
            }
        }
        std::cout << std::endl;
    }
    
    template <typename T>
    void CTree<T>::inorderTravel()
    {
        std::stack<CTree<T>::node_pointer, std::list<CTree<T>::node_pointer> > S;
        if (root)
        {
            S.push(root);
        }
    
        while (!S.empty())
        {
            CTree<T>::node_pointer node = S.top();
            if (node->left && node->left->color == WHITE)
            {
                S.push(node->left);
            }
            else
            {
                std::cout << node->d << " ";
                node->color = BLACK;
                S.pop();
                if (node->right)
                {
                    S.push(node->right);
                }
            }
        }
        std::cout << std::endl;
    }
    
    template <typename T>
    void CTree<T>::postorderTravel()
    {
        std::stack<CTree<T>::node_pointer, std::list<CTree<T>::node_pointer> > S;
        if (root)
        {
            S.push(root);
        }
    
        while (!S.empty())
        {
            CTree<T>::node_pointer node = S.top();
            int nextTra = 1;
    
            if (node->right && node->right->color == WHITE)
            {
                S.push(node->right);
                nextTra = 0;
            }
            if (node->left && node->left->color == WHITE)
            {
                S.push(node->left);
                nextTra = 0;
            }
            if (nextTra)
            {
                std::cout << node->d << " ";
                node->color = BLACK;
                S.pop();
            }
        }
        std::cout << std::endl;
    }
    
    template <typename T>
    void CTree<T>::layerTravle()
    {
        std::queue<CTree<T>::node_pointer, std::list<CTree<T>::node_pointer> > Q;
        if (root)
        {
            Q.push(root);
        }
    
        while (!Q.empty())
        {
            CTree<T>::node_pointer node = Q.front();
            std::cout << node->d << " ";
            Q.pop();
            if (node->left)
            {
                Q.push(node->left);
            }
            if (node->right)
            {
                Q.push(node->right);
            }
        }
        std::cout << std::endl;
    }
    
    template <typename T>
    int CTree<T>::_height(CTree<T>::node_pointer root)
    {
        if (root == NULL)
        {
            return 0;
        }
    
        int lh = _height(root->left);
        int rh = _height(root->right);
    
        return lh > rh ? lh + 1 : rh + 1;
    }
    
    template <typename T>
    int CTree<T>::height()
    {
        return _height(root);
    }
    
    int main()
    {
        int arr[] = {6,3,4,1,3,8,9,7,6,0,2};
        int len = sizeof(arr)/sizeof(int);
        CTree<int> tree(arr, len);
    
        tree.preorderTravel();
        tree.postorderTravel();
        tree.layerTravle();
    
        printf("%d
    ", tree.height());
    
        return 0;
    }
  • 相关阅读:
    Autofs
    markdown 基本语法
    Why Linux Doesn’t Need Defragmenting
    How to reconfigure installed dpkg package (tzdata, locales)
    weblogic性能监控
    exec
    在Oracle中查询表的大小
    hadoop主要概念的理解和学习
    ORACLE ASM中查询表空间使用情况、数据文件路径、裸设备磁盘总大小剩余大小
    linux 查看内存和cpu占用比较多的进程
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/9919086.html
Copyright © 2011-2022 走看看