二叉树常见的面试题(1)

来源:互联网 发布:影音后期制作软件大全 编辑:程序博客网 时间:2024/05/19 14:50
#pragma once#include<iostream>#include<windows.h>#include<string.h>#include<queue>#include<stack>using namespace std;// 孩子表示法template<class T>struct BinaryTreeNode{    BinaryTreeNode(const T& value)    : _value(value)    , _pLeft(NULL)    , _pRight(NULL)    {}    T _value;    BinaryTreeNode<T>* _pLeft;   // 左孩子    BinaryTreeNode<T>* _pRight;  // 右孩子};//创建(遍历)二叉树的时间复杂度O(N)template<class T>class BinaryTree{    typedef BinaryTreeNode<T> Node;public:    BinaryTree()        : _pRoot(NULL)    {}    BinaryTree(const T arr[], size_t size, const T& invalid)    {        size_t index = 0;        _CreateBinaryTree(_pRoot, arr, size, index, invalid);    }    BinaryTree(const BinaryTree<T>& bt)    {        _pRoot = _CopyBirnaryTree(bt._pRoot);    }    BinaryTree<T>& operator=(const BinaryTree<T>& bt)    {        if (this != &bt)        {            _DestroyBinaryTree(_pRoot);            _pRoot=_CopyBirnaryTree(bt._pRoot);        }        return *this;    }    ~BinaryTree()    {        _DestroyBinaryTree(_pRoot);    }    ///////////////////////////////////////////////////////////////    void PreOrder()    {        cout << "PreOrder:" << endl;        _PreOrder(_pRoot);        cout << endl;    }    void PreOrder_Nor()    {        cout << "PreOrder_Nor:" << endl;        _PreOrder_Nor(_pRoot);        cout << endl;    }    void InOrder()    {        cout << "InOrder:" << endl;        _InOrder(_pRoot);        cout << endl;    }    void InOrder_Nor()    {        cout << "InOrder_Nor:" << endl;        _InOrder_Nor(_pRoot);        cout << endl;    }    void PostOrder()    {        cout << "PostOrder:" << endl;        _PostOrder(_pRoot);        cout << endl;    }    void PostOrder_Nor()    {        cout << "PostOrder_Nor:" << endl;        _PostOrder_Nor(_pRoot);        cout << endl;    }    void LevelOrder()//******考点********队列***    {        cout << "LevelOrde:" << endl;        _LevelOrder(_pRoot);        cout << endl;    }    Node* Find(const T& value)    {        return _Find(_pRoot, value);    }    //二叉树中和为某一值的路径    void FindPath(size_t WantSum)    {        size_t Cursum = 0;        vector<int>path;        _FindPath(_pRoot, WantSum, path, Cursum);    }    Node* Parent(Node* pCur)    {        return _Parent(_pRoot, pCur);    }    Node* GetLeftChild(Node* pCur)    {        return (pCur == NULL) ? NULL : pCur->_pLeft;    }    Node* GetRightChild(Node* pCur)    {        return (pCur == NULL) ? NULL : pCur->_pRight;    }    size_t Height()    {        return _Height(_pRoot);    }    size_t GetLeefCount()    {        return _GetLeefCount(_pRoot);    }    size_t GetKLevelCount(size_t k)    {        return _GetKLevelCount(_pRoot, k);    }    void BinaryMirror_Nor()    {        return _BinaryMirror_Nor();    }    void BinaryMirror()    {        return _BinaryMirror(_pRoot);    }private:    // 根—左—右  —>构造二叉树    void _CreateBinaryTree(Node* &pRoot, const T arr[], size_t size, size_t& index, const T& invalid)    {        if (index < size&&arr[index] != invalid)//顺序不能颠倒,防止越界访问        {            //创建根节点            pRoot = new Node(arr[index]);            //创建左孩子节点            _CreateBinaryTree(pRoot->_pLeft, arr, size, ++index, invalid);            //创建右孩子节点(看不见右孩子创建节点过程)            _CreateBinaryTree(pRoot->_pRight, arr, size, ++index, invalid);        }    }    // pRoot-->被拷贝树的根节点    Node* _CopyBirnaryTree(Node* pRoot)    {        Node* pNewRoot = NULL;        if (pRoot)        {            pNewRoot = new Node(pRoot[0]);//拷贝根节点            pNewRoot->_pLeft = _CopyBirnaryTree(pRoot->_pLeft); //拷贝左子树            pNewRoot->_pRight = _CopyBirnaryTree(pRoot->_pRight);//拷右左子树        }        return pNewRoot;    }    void _DestroyBinaryTree(Node*& pRoot)    {        if (pRoot)        {            _DestroyBinaryTree(pRoot->_pLeft);            _DestroyBinaryTree(pRoot->_pRight);            delete pRoot;            pRoot = NULL;        }    }    ////////////////////////////////////////////////////////////////    //前序遍历递归    // 前序:访问根节点--->访问根节点的左子树--->访问根节点的右子树    void _PreOrder(Node* pRoot)      {        if (pRoot)        {            cout << pRoot->_value << " ";            _PreOrder(pRoot->_pLeft);            _PreOrder(pRoot->_pRight);        }    }    //前序遍历非递归    void _PreOrder_Nor(Node*pRoot)    {        if (NULL == pRoot)            return;        stack<Node*>s;        s.push(pRoot);        while (!s.empty())        {            Node*pCur = s.top();            cout << pCur->_value << " ";            s.pop();            if (pCur->_pRight)                s.push(pCur->_pRight);            if (pCur->_pLeft)                s.push(pCur->_pLeft);        }    }    //中序遍历递归    void _InOrder(Node* pRoot)    {        if (pRoot)        {             _InOrder(pRoot->_pLeft);            cout << pRoot->_value << " ";            _InOrder(pRoot->_pRight);        }    }    //中序遍历非递归    void _InOrder_Nor(Node*pRoot)    {        if (NULL == pRoot)            return;        stack<Node*>s;        Node*pCur = pRoot;        while (pCur || !s.empty())        {            while (pCur)            {  // 找到最左边的孩子,并把所经过路径的结点保存下来                s.push(pCur);                pCur = pCur->_pLeft;            }            //出了内层循环,pCur为空,栈顶元素为最左边的孩子            pCur = s.top();            cout << pCur->_value << " ";            s.pop();            pCur = pCur->_pRight;        }    }    // 后序遍历:遍历根的左子树-->遍历根的右子树-->遍历根节点    void _PostOrder(Node* pRoot)    {        if (pRoot)        {            _PostOrder(pRoot->_pLeft);            _PostOrder(pRoot->_pRight);            cout << pRoot->_value << " ";        }    }    //后序遍历非递归    void _PostOrder_Nor(Node*pRoot)    {        if (NULL == pRoot)            return;        stack<Node*>s;        Node*pCur = pRoot;        Node*Prev = NULL;//保存上次入栈的结点        while (pCur || !s.empty())        {            while (pCur)            {  // 找到最左边的孩子,并把所经过路径的结点保存下来                s.push(pCur);                pCur = pCur->_pLeft;            }            Node*pTop = s.top();            if (NULL == pTop->_pRight || Prev == pTop->_pRight)//没有Prev == pTop->_pRight会4256666666......死循环下去            {                cout << pTop->_value << " ";                Prev = pTop; //保存上次入栈的结点                s.pop();            }            else            {                pCur = pTop;//pCur在while出来之后为NULL,所以要更新pCur的值,少了这句,崩溃                pCur = pCur->_pRight;            }        }    }    // 层序遍历    void _LevelOrder(Node*pRoot)//******考点********队列***    {        if (NULL == pRoot)            return;        queue<Node*>q;        q.push(pRoot);//保存的是结点的地址,地址出了队列,但是树并没有改变        while (!q.empty())        {            Node*pcur = q.front();            cout << pcur->_value << " ";            if (pcur->_pLeft)//左不为空入队列            {                q.push(pcur->_pLeft);            }            if (pcur->_pRight)//右不为空入队列            {                q.push(pcur->_pRight);            }            q.pop();        }        cout << endl;    }    //二叉树中和为某一值的路径    void _FindPath(Node*pRoot, size_t WantSum, vector<int>&path, size_t CurSum)    {        CurSum += pRoot->_value;        path.push_back(pRoot->_value);        //如果是叶子结点,并且路径上结点的和等于输入的值,打印这条路径        if (CurSum == WantSum&&NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)        {            cout << WantSum << "path is found:" << endl;            vector<int>::iterator it = path.begin();            while (!path.empty() && it != path.end())            {                cout << *it << " ";                it++;            }            cout << endl;        }        if (pRoot->_pLeft)        {            _FindPath(pRoot->_pLeft, WantSum, path, CurSum);        }        if (pRoot->_pRight)        {            _FindPath(pRoot->_pRight, WantSum, path, CurSum);        }        //在返回父节点之前,在路径上删除当前节点        path.pop_back();    }    //树中查找一个节点    Node* _Find(Node* pRoot, const T& value)    {         Node*pCur = NULL;        if (NULL == pRoot)            return NULL;        if (pRoot->_value == value)        {            return pRoot;        }        pCur = _Find(pRoot->_pLeft, value);        if (NULL!=pCur)           return pCur;        return _Find(pRoot->_pRight, value);    }    //求一个节点的双亲    Node* _Parent(Node* pRoot, Node* pCur)    {        if (NULL == pRoot)//树空            return NULL;        if (NULL==pRoot->_pLeft&&NULL == pRoot->_pRight)//只有一个节点            return NULL;        if (pRoot == pCur)            return NULL;//所找结点刚好为根结点        if (pCur == pRoot->_pLeft || pCur == pRoot->_pRight)            return pRoot;        Node*parent = NULL;        parent = _Parent(pRoot->_pLeft, pCur);//从左子树中找        if (NULL != pCur)            return pCur;        return _Parent(pRoot->_pLeft, pCur);//从右子树中找    }    //求二叉树的高度    size_t _Height(Node* pRoot)    {        if (NULL == pRoot)            return 0;        if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)//一个节点            return 1;        size_t Left_Height=_Height(pRoot->_pLeft);//左子树的高度        size_t Right_Height = _Height(pRoot->_pRight);//右子树的高度        return Left_Height > Right_Height ? Left_Height + 1 : Right_Height + 1;    }    //求叶子节点的个数    size_t _GetLeefCount(Node* pRoot)    {        if (NULL == pRoot)            return 0;        if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)//一个节点            return 1;        size_t Left_LeefCount=_GetLeefCount(pRoot->_pLeft);        size_t Right_LeefCount = _GetLeefCount(pRoot->_pRight);        return Left_LeefCount + Right_LeefCount;    }    //求第K层节点的个数    size_t _GetKLevelCount(Node* pRoot, size_t k)    {        if (NULL == pRoot || k<1)//此处省略了K>Height(_pRoot),因为大于树的            return 0;           //高度时返回0        if (k == 1)            return 1;        size_t LeftKLevelCount=_GetKLevelCount(pRoot->_pLeft, k - 1);        size_t RighttKLevelCount = _GetKLevelCount(pRoot->_pRight, k - 1);        return LeftKLevelCount + RighttKLevelCount;    }    //二叉树的镜像—递归    void _BinaryMirror(Node* pRoot)    {        if (NULL == pRoot)            return;        swap(pRoot->_pLeft, pRoot->_pRight);        _BinaryMirror(pRoot->_pLeft);        _BinaryMirror(pRoot->_pRight);    }    //二叉树的镜像—非递归    void _BinaryMirror_Nor()    {        if (NULL == _pRoot)            return;        queue<Node*>q;        q.push(_pRoot);        while (!q.empty())        {            Node*pCur = q.front();            if (pCur)            {                q.push(pCur->_pLeft);            }            if (pCur)            {                q.push(pCur->_pRight);            }            if (NULL!=pCur)//必须判断            swap(pCur->_pLeft, pCur->_pRight);            q.pop();        }    }private:    Node* _pRoot;   // 指向树的根节点};