二叉树基本操作汇总练习

来源:互联网 发布:c语言读入txt文本文件 编辑:程序博客网 时间:2024/06/05 18:16
#include<iostream>#include<queue>#include<assert.h>using namespace std;//二叉树的构建、销毁、赋值,拷贝构造。、遍历、修改、查找、template<typename T>struct BinaryTreeNode{    BinaryTreeNode<T>(const T&data=T())    : _data(data)    , _pLeft(NULL)    , _pRight(NULL)    {}    T _data;    BinaryTreeNode<T>* _pLeft;    BinaryTreeNode<T>*_pRight;};template<typename T>class BinaryTree{    typedef BinaryTreeNode<T> Node;public:    BinaryTree()        :_pRoot(NULL)        , _invalid(T())    {    }    BinaryTree(const T arr[], const size_t length,const T& invalid)    {        size_t index = 0;        _pRoot = _CreateTree(_pRoot, arr, length, index,invalid);    }    //前序遍历    void PreOrder()    {        _PreOrder(_pRoot);    }    void InOrder()    {        _InOrder(_pRoot);    }    void MidOrder()    {        _MidOrder(_pRoot);    }    //查找两节点的最近公共祖先    void ComParent(Node* node1, Node* node2)    {        //算法思路:1.判断两个节点的在根节点的左、右位置。        //2,递归下去进行查找        if (_pRoot == NULL || node1 == NULL || node2 == NULL)        {            return NULL;        }        bool left1 = Find(node1->_data);        bool left2 = Find(node2->_data);        if ()        {        }    }    //Node* GetLastCommonAncestor(Node* root, Node* node1, Node* node2)    //{    //  if (root == NULL || node1 == NULL || node2 == NULL)    //  {    //      return NULL;    //  }    //  if (node1 == root || node2 == root)//前序遍历框架    //  {    //      return root;    //  }    //  Node* left_lca = GetLastCommonAncestor(root->_pLeft,node1,node2);    //  Node* right_lca = GetLastCommonAncestor(root->_pRight, node1, node2);    //  if (left_lca&&right_lca)    //  {    //      return root;    //  }    //  else if (left_lca==NULL)    //  {    //      return right_lca;    //  }    //  else    //  {    //      return left_lca;    //  }    //}    //递归进行查找    Node* GetLastCommonAncestor(Node* root, Node* node1, Node* node2)    {        if (root == NULL || node1 == NULL || node2 == NULL)        {            return NULL;        }        if (root == node1 || root == node2)        {            return root;        }        Node* left_lca = GetLastCommonAncestor(root->_pLeft,node1,node2);        Node* cur = NULL;        if (left_lca)        {            //判断是否为父子关系            cur = GetLastCommonAncestor(left_lca->_pLeft, node1, node2);            if (cur == NULL)            {                cur = GetLastCommonAncestor(left_lca->_pRight,node1,node2);            }            if ((cur == node1) && (left_lca == node2) || (cur == node2) && (left_lca == node1))                return root;        }        Node* right_lca = GetLastCommonAncestor(root->_pRight,node1,node2);        if (right_lca)        {            //判断受否具有祖孙关系            cur = GetLastCommonAncestor(right_lca->_pLeft, node1, node2);            if (cur == NULL)            {                cur = GetLastCommonAncestor(right_lca->_pRight, node1, node2);            }            if ((cur == node1) && (right_lca == node2) || (cur == node2) && (right_lca == node1))                return root;        }        if (left_lca&&right_lca)//一个在root的左结点,一个在root的右节点,则返回root        {            return root;        }        else if (left_lca)        {            return left_lca;        }        else        {            return right_lca;        }    }    //根据前序和中序构建一颗二叉树     BinaryTree( T pre[], size_t n1,  T mid[], size_t n2)    {        if (n1 != n2)        {            _pRoot= NULL;        }        else        {            _pRoot = CreatTreeFromPriAndMid(pre, mid, n2);        }    }    Node* CreatTreeFromPriAndMid(T pre[], T mid[], size_t n)    {        //根据前序遍历特点,在中序中进行划分区间,来创建二叉树        if (n < 1)        {            return NULL;        }        Node* root = new Node(pre[0]);        size_t i = 0;        for (; i < n&&mid[i] != pre[0]; ++i)//左闭右开        {        }        size_t left = i;//开区间        size_t right = n- i - 1;//闭区间        if (left>0)        {            root->_pLeft = CreatTreeFromPriAndMid(&pre[1], mid, left);//其根节点已经创建好了        }        if (right > 0)        {            root->_pRight = CreatTreeFromPriAndMid(&pre[left+1], &mid[left+1], right);        }        return root;    }    void LevelOrder()    {    //层序遍历        //利用队列实现因为需要先入的先访问,如果按照栈的特点来做,访问左孩子后,为了方便访问下一层,需要保存它的左右孩子,无法访问按层序访问右孩子,因为已经插上来了        //所以我们使用队列,就可以满足这一点        //只需要一个循环就能实现        if (_pRoot != NULL)        {            queue<Node*>q;            q.push(_pRoot);            while (!q.empty())            {                Node*cur = q.front();                q.pop();                cout << cur->_data<<" ";                if (cur->_pLeft)                {                    q.push(cur->_pLeft);                }                if (cur->_pRight)                {                    q.push(cur->_pRight);                }            }        }    }    //拷贝构造函数    BinaryTree(const BinaryTree<T>& Bt)    {        //根据指针拷贝对象        _pRoot = _Copy(Bt._pRoot);    }    //赋值函数    BinaryTree<T>* operator =(BinaryTree<T>Bt)    {        //基本框架一样    或者采用新赋值方法,交换两者的空间。然后函数结束,销毁临时对象        if (_pRoot != &Bt._pRoot)        {            //拷贝            BinaryTree<T> temp(Bt);            Destory(_pRoot);            //释放新空间            _pRoot = temp._pRoot;        }        return *this;    }    //查找    Node* Find(const T& t)    {        return _Find(_pRoot, t);    }    //找出该节点的父亲结点    //思路:    //求叶子节点的个数    Node* Parent(Node* cTest)    {        return _Parent(_pRoot,cTest);    }    Node* _Parent(Node* root ,Node * cTest)    {        if (root == NULL)        {            return NULL;        }        if (root->_pLeft == NULL&&root->_pRight == NULL)        {            return NULL;        }        if (root->_pLeft == cTest||root->_pRight==cTest)        {            return root;        }        Node* parent= _Parent(root->_pLeft, cTest);        if (parent)        {            return  parent;        }        return _Parent(root->_pRight,cTest);    }    //求一个节点的父亲结点—方法二    //利用层序遍历(这一次我们自己实现一个队列)的思路如果结点等于其左子树或者右子树,将其返回    Node* ParentNode(Node * node)    {        if (node == NULL || _pRoot == node)        {            return NULL;        }        int max = 50;        int front, rear;        Node* current, *child;        int count = 0;        if (node != NULL)        {            Node  queue[max];            front = rear = 0;            queue[rear++] = node;            count++;            while (count != 0)            {                current = queue[front];                if (current->_pLeft)                {                    child = current->_pLeft;                    if (node == child)                    {                        return current;                    }                    else                    {                        //入队                        queue[rear] = child;                        rear = (rear + 1)%max;//循环队列实现方式                        count++;                    }                }                if (current->_pRight)                {                    child = current->_pRight;                    if (child == node)                    {                        return current;                    }                    else                    {                        queue[rear] = child;                        rear = (rear + 1) % max;                        count++;                    }                }                front = (front + 1) % max;                count--;            }        }        return NULL;    }    //求数的高度    size_t Height()    {        return _Height(_pRoot);    }    //节点个数    size_t size()    {     size_t count = 0;     _size(_pRoot,count);     return count;    }    //叶子节点个数    size_t leaf()    {        size_t count = 0;        _leaf(_pRoot,count);        return count;    }    ~BinaryTree()    {    //销毁函数        DestoryTree(_pRoot);        _pRoot = NULL;    }    /******************************************************/    //              二叉树的非递归操作    /******************************************************/    void InOrderNoR()    {        _InOrderNoR(_pRoot);    }    //获取父亲结点    Node* GetParent(Node* pRoot,Node* pNode)    {        if (_pRoot == NULL || pNode == NULL)return NULL;         if (_pRoot == pNode)return NULL;        if (pRoot->_pLeft == pNode || pRoot->_pRight == NULL)        {            return pRoot;        }        GetParent(pRoot->_pLeft,pNode);        GetParent(pRoot->_pRight,pNode);        return NULL;    }    //获取树的高度    size_t Height(Node* pRoot)    {        if (pRoot == NULL)            return 0;        size_t left = Height(pRoot->_pLeft);        size_t right = Height(pRoot->_pRight);        return left > right ? left + 1 : right + 1;    }    size_t leafSize()    {        if (pRoot == NULL)        {            return 0;        }        if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL)        {            return 1;        }        return Height(pRoot->_pLeft) + Height(pRoot->_pRight);    }    //获取第k层结点的个数    size_t GetKthLevelCount(Node* pRoot ,size_t k)    {        if (pRoot == NULL||k<1)        {            return 0;        }        if (k == 1)        {            return 1;        }        return GetKthLevelCount(pRoot->_pLeft,k-1) + GetKthLevelCount(pRoot->_pRight,k-1);    }    //获取一颗二叉树的镜像    //利用层序遍历进行左右节点进行交换    Node* mirror(Node* pRoot)    {        if (pRoot == NULL || (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL))        {            return pRoot;        }        //队列来实现        queue<Node* >q;        q.push(pRoot);        while (!q.empty())        {            Node* pCur = q.front();            q.pop();            if (pCur->_pLeft)            {                q.push(pCur->_pLeft);            }            if (pCur->_pRight)            {                q.push(pCur->_pRight);            }            swap(pCur->_pLeft, pCur->_pRight);        }    }protected:    //递归创建是一个二叉树    //Node*_CreateTree(Node* pRoot, const T arr[], const size_t length, size_t & index,const T &invalid)    //{    //  if (pRoot == NULL)    //  {    //      if (index < length&&arr[index] != invalid)    //      {    //          pRoot = new Node(arr[index]);    //      }    //  }    //  if (pRoot)    //  {    //      _CreateTree(pRoot->_pLeft, arr, length, ++index, invalid);    //      _CreateTree(pRoot->_pRight, arr, length, ++index, invalid);    //  }    //  return pRoot;    //}    Node* _CreateTree(Node* &pRoot,const T arr[],const size_t length,size_t&index,const T&invalid)    {        Node* temp = NULL;        if (index<length&&arr[index]!=invalid)//pRoot为空不能作为遍历结束条件        {            //先对根进行操作            temp = new Node(arr[index]);            pRoot = temp;            _CreateTree(pRoot->_pLeft, arr, length, ++index, invalid);//在遍历左子树            _CreateTree(pRoot->_pRight, arr, length, ++index, invalid);//在遍历右子树        }        return temp;    }    //四种遍历:前中后。层    void _PreOrder(Node* pRoot)    {        if (pRoot)        {            cout << pRoot->_data << " ";            _PreOrder(pRoot->_pLeft);            _PreOrder(pRoot->_pRight);        }    }    void _InOrder(Node* pRoot)    {        if (pRoot)        {            _InOrder(pRoot->_pLeft);            _InOrder(pRoot->_pRight);            cout << pRoot->_data << " ";        }    }    void _MidOrder(Node* pRoot)    {        if (pRoot)        {            _PreOrder(pRoot->_pLeft);            cout << pRoot->_data << " " << endl;            _PreOrder(pRoot->_pRight);        }           }    //拷贝构造函数    //Node* _Copy(Node* node)    //{    //  Node* cur = node;    //  Node* root = NULL;    //  if (cur)    //  {    //      root = new Node(cur->_data);    //      root->_pLeft = _Copy(cur->_pLeft);    //      root->_pRight = _Copy(cur->_pRight);    //  }    //  return root;    //    //}    Node* _Copy(Node* node)    {        Node* root = NULL;        if (node)        {            root = new Node(node->_data);            root->_pLeft = _Copy(node->_pLeft);            root->_pRight = _Copy(node->_pRight);        }        return root;    }    Node* _Find(Node* root, const T & t)    {        if (root)        {            if (root->_data == t)            {                return root;            }            Node* ret = _Find(root->_pLeft, t);      //此处不应该如此,因为一直递归到最深处,假如没有找到,肯定函数返回为NULL,整个函数结束            if (ret)            {                return ret;            }            return _Find(root->_pRight, t);        }        return root;    }    size_t _Height(Node* root)    {        //左右子树最深的个数加1就是当前树的深度        if (root == NULL)        {            return 0;        }        size_t left = _Height(root->_pLeft);        size_t right = _Height(root->_pRight);        return left > right ? left + 1 : right + 1;    }    void _size(Node* root,size_t & count)    {        if (root)        {            if (root->_pLeft == NULL&&root->_pRight == NULL)            {                return;            }            _size(root->_pLeft, ++count);            _size(root->_pRight, ++count);        }    }    size_t _leaf(Node* root,size_t &count)    {        if (root == NULL)        {            return 0;        }        if (root->_pLeft == NULL&&root->_pRight == NULL)        {            count++;        }        _leaf(root->_pLeft, count);        _leaf(root->_pRight, count);        return count;    }    //销毁函数    void DestoryTree(Node*pRoot)    {        if (pRoot)        {            DestoryTree(pRoot->_pLeft);            DestoryTree(pRoot->_pRight);            delete pRoot;            pRoot = NULL;        }    }    //非递归前序遍历:两种实现    //思路:利用栈模拟递归,保存当前函数的参数,方便后面进行取操作    void _PreOrderNoR(Node* _pRoot)    {        if (NULL == _pRoot)return;        stack<Node*>st;        st.push(_pRoot);        while (!st.empty())        {            Node* pCur = st.top();            st.pop();            cout << pCur->_data << " ";            //不为空,入栈            if (pCur->_pRight)            {                st.push(pCur->_pRight);            }            if (pCur->_pLeft)            {                st.push(pCur->_pLeft);            }        }    }    void _InOrderNoR(Node* _pRoot)    {        //中序遍历  万能模板        if (!_pRoot)        {            return;        }        stack<Node* >st;        st.push(_pRoot);        Node* pCur = st.top();        st.pop();        while (pCur||(!st.empty()))        {            //走到最左子树,保存其路径的结点            while (pCur)            {                st.push(pCur);                pCur = pCur->_pLeft;            }            //打印节点信息            pCur = st.pop();            cout << pCur->_data << " ";            //左子树访问完,访问其右子树            pCur = pCur->_pRight;        }    }    //中序遍历    //后序遍历非递归实现    //思路:左、右、根  进行遍历public:    Node* _pRoot;    T _invalid;};void Test(){    int arr[] = { 1,2, 4, '#', '#', '#', 3, 5, '#', '#', 6 };    BinaryTree<int> Bt(arr,sizeof(arr)/sizeof(arr[0]),'#');    //Bt.MidOrder();    //Bt.InOrder();    //Bt.PreOrder();    //Bt.LevelOrder();    /*BinaryTree<int> Bt1(Bt);    Bt1.PreOrder();    cout << endl;    BinaryTreeNode<int>* cur = Bt1.Find(6);    cout << cur->_data << " ";*/    BinaryTreeNode<int>*  cur = Bt.Find(6);    BinaryTreeNode<int>*parent = Bt.Parent(cur);    cout << parent->_data << endl;    cout << "size::" << Bt.size() << " " << "Height::" << Bt.Height() << " Leaf::" << Bt.leaf() << endl;}void Test2(){    int arr[] = { 1, 2, 4, '#', '#', '#', 3, 5, '#', '#', 6 };    BinaryTree<int> Bt(arr, sizeof(arr) / sizeof(arr[0]), '#');    BinaryTreeNode<int>* node1 = Bt.Find(5);    BinaryTreeNode<int>* node2 = Bt.Find(6);    BinaryTreeNode<int>* ret = Bt.GetLastCommonAncestor(Bt._pRoot,node1,node2);    cout << node1->_data << "和" << node2->_data << "的公共祖先是:" << ret->_data;}void Test3(){    int pre[] = {1,2,4,3,5,6};    int mid[] = {4,2,1,5,3,6};    BinaryTree<int> bt(pre,6,mid,6);    bt.PreOrder();}int main(){    Test3();    return 0;}
0 0
原创粉丝点击