二叉树的创建和基本操作(递归和非递归)

来源:互联网 发布:淘宝代付可以用微信吗 编辑:程序博客网 时间:2024/06/04 18:03

二叉树的定义在这里不做陈述,我们直接来看看如何实现一个二叉树的创建(c++)

首先定义结点,这里我们呢用结构体来创建

template<typename T>struct BinaryTreeNode   //创建孩子二叉树的结点{    BinaryTreeNode(const T& data = T())    :_data(data)    , _pLeft(NULL)    , _pRight(NULL)    {}    T _data;    BinaryTreeNode* _pLeft;    BinaryTreeNode* _pRight;};

定义好结点之后我们就可以来想办法创建一个二叉树类,其中包含二叉树的创建和基本操作

template<typename T>class BinaryTree{    typedef BinaryTreeNode<T> Node;public:    BinaryTree()        : _pRoot()    {}    /***********用函数封装来做************/    BinaryTree(const T* array, size_t size, const T& invalid)  //构造函数构造二叉树    {        size_t index = 0;        _pRoot = CreatTree(array, size, index, invalid);    }    BinaryTree(const BinaryTree<T>& b)  //拷贝构造一个相同的二叉树    {        _pRoot = Copy(b._pRoot);    }    BinaryTree& operator=(BinaryTree<T>& b)  //重载=    {        if (this != &b)  //防止自己给自己赋值        {            BinaryTree<T> tem(b);            std::swap(_pRoot, tem._pRoot);        }        return *this;    }    ~BinaryTree()  //析构函数释放树    {        Destory(_pRoot);    }    size_t _Leaf()  //求叶子结点个数    {        return Leaf(_pRoot);    }    size_t _Size()  //求结点个数    {        return Size(_pRoot);    }    size_t _Depth()  //求树的深度    {        return Depth(_pRoot);    }    void _PreOder()  //先序遍历    {        PreOder(_pRoot);        cout << endl;    }    void _InOder()  //中序遍历    {        InOder(_pRoot);        cout << endl;    }    void _BackOder()  //后序遍历    {        BackOder(_pRoot);        cout << endl;    }protected:    Node* _pRoot;}

创建好这个二叉树类之后我们来将其中的功能进行相应的实现(这里我将所有的函数实现都已private的形式写在了类内部)

··········创建二叉树/*先序递归创建二叉树*/        Node* CreatTree(const T* array, size_t size, size_t& index, const T& invalid)    {        assert(array);        Node* pRoot = NULL;        if (index < size&&array[index] != invalid)        {            pRoot = new Node(array[index]);            pRoot->_pLeft = CreatTree(array, size, ++index, invalid);            pRoot->_pRight = CreatTree(array, size, ++index, invalid);        }        return pRoot;    }/*非递归创建二叉树*/    Node *CreatTree(const T* a, size_t size, size_t index, const T& invalid)    {        stack<Node*> s;        Node* pRoot = new Node(a[index++]);        int flag = 1;         //flag  =1创建左孩子,=2创建右孩子,=3出栈          s.push(pRoot);        Node *pPre = NULL;        Node *pCur = NULL;        while (index<size)        {            if (flag == 1)      //创建左孩子              {                if (a[index] == invalid)     //如果左孩子为空,则flag=2创建右孩子                  {                    flag = 2;                }                else                {                    pCur = new Node(a[index]);                    pPre = s.top();                    pPre->_pLeft = pCur;          //链接到左指针上                      s.push(pCur);               //将新节点压入栈中                  }            }            else if (flag == 2)              //flag=2,创建右孩子              {                if (a[index] == invalid)        //如果右孩子为空,则flag=3准备出栈                  {                    flag = 3;                }                else                {                    pCur = new Node(a[index]);                    pPre = s.top();                    pPre->_pRight = pCur;          //链接到左指针上                      s.push(pCur);               //将新节点压入栈中                      flag = 1;                  //再创建新结点的左孩子                  }            }            else            {                if (!s.empty())                {                    pPre = s.top();                    s.pop();                }                //如果已经出栈的元素是当前栈顶的右孩子,则表示这个结点的左右子树已经创建完毕,则一直出栈                  while (!s.empty() && s.top()->_pRight == pPre)                {                    pPre = s.top();                    s.pop();                }                flag = 2;                index--;            }            index++;        }        return pRoot;    }··········先序遍历/*递归先序遍历*/    void PreOder(Node* pRoot)    {        Node* pCur = pRoot;        if (pCur)        {            cout << pCur->_data << " ";            PreOder(pCur->_pLeft);            PreOder(pCur->_pRight);        }    }/*非递归先序遍历*/    void PreOder(Node* _pRoot)    {        assert(_pRoot);        Node *pRoot = _pRoot;        stack<Node*> s;        s.push(pRoot);        int flag = 1;        Node *pCur = NULL;        while (!s.empty())        {            pCur = s.top();            if (flag == 1)                  //遍历左子树              {                if (pCur->_pLeft == NULL)    //如果左子树为空,则flag=2                  {                    flag = 2;                }                else                {                    cout << pCur->_Data << " ";    //先序输出,先输出根结点                      s.push(pCur->_pLeft);                }            }            else if (flag == 2)            {                if (pCur->_pRight == NULL)                {                    flag = 3;                }                else                {                    s.push(pCur->_pRight);                    flag = 1;                }            }            else            {                Node *pPre = NULL;                if (!s.empty())                {                    pPre = s.top();                    s.pop();                }                pCur = pPre;                while (!s.empty() && s.top()->_pRight == pPre)  //将输出过的结点出栈                  {                    pPre = s.top();                    s.pop();                }                if (!s.empty())         //输出右子树的叶子节点                  {                    cout << pCur->_Data << " ";                }                flag = 2;            }        }        cout << endl;    }·········中序遍历/*递归中序遍历*/    void InOder(Node* pRoot)    {        Node* pCur = pRoot;        if (pCur)        {            InOder(pCur->_pLeft);            cout << pCur->_data << " ";            InOder(pCur->_pRight);        }    }/*非递归中序遍历*/    void InOder(Node* _pRoot)    {        assert(_pRoot);        Node *pRoot = _pRoot;        stack<Node*> s;        s.push(pRoot);        int flag = 1;        while (!s.empty())        {            Node *pCur = s.top();            if (flag == 1)                  //先遍历左子树              {                if (pCur->_pLeft == NULL)                {                    flag = 2;                }                else                {                    s.push(pCur->_pLeft);                }            }            else if (flag == 2)        //遍历右子树              {                if (pCur->_pRight == NULL)                {                    flag = 3;                }                else                {                    cout << pCur->_Data << " ";        //输出右子树的跟结点                      s.push(pCur->_pRight);                    flag = 1;                }            }            else            {                Node* pPre = NULL;                if (!s.empty())                {                    pPre = s.top();                    s.pop();                }                cout << pPre->_Data << " ";          //输出左子树结点和左子树的根结点                  while (!s.empty() && s.top()->_pRight == pPre)                {                    pPre = s.top();                    s.pop();                }                flag = 2;            }        }        cout << endl;    }········后序遍历/*递归后序遍历*/    void BackOder(Node* pRoot)    {        Node* pCur = pRoot;        if (pCur)        {            BackOder(pCur->_pLeft);            BackOder(pCur->_pRight);            cout << pCur->_data << " ";        }    }/*非递归后序遍历*/    void BackOder(Node* _pRoot)    {        assert(_pRoot);        Node *pRoot = _pRoot;        stack<Node*> s;        int flag = 1;       //=1遍历左子树,=2 遍历右子树,=3 输出结点          s.push(pRoot);       //根节点入栈          Node *pCur = NULL;        while (!s.empty())        {            pCur = s.top();            if (flag == 1)              //遍历左子树              {                if (pCur->_pLeft == NULL)   //如果左子树为空,则flag=2,准备遍历右子树                  {                    flag = 2;                }                else                {                    s.push(pCur->_pLeft);                }            }            else if (flag == 2)             //遍历右子树              {                if (pCur->_pRight == NULL)       //右子树为空,准备输出结点                  {                    flag = 3;                }                else                {                    s.push(pCur->_pRight);                    flag = 1;                //遍历当前结点的左子树                  }            }            else            {                Node *pPre = NULL;                if (!s.empty())                {                    pPre = s.top();    //保存当前栈顶元素                      s.pop();          //抛出栈顶元素                  }                cout << pPre->_Data << " ";    //输出结点的信息                  //如果当前栈顶元素的右子树是pPre,则抛出pPre之后按照后序也要抛出栈顶元素                  while (!s.empty() && s.top()->_pRight == pPre)                {                    pPre = s.top();    //保存当前栈顶元素                      s.pop();          //抛出栈顶元素                      cout << pPre->_Data << " ";    //输出结点的信息                  }                flag = 2;            }        }        cout << endl;    }········求叶子结点个数/*递归*/        size_t Leaf(Node* pRoot)    {        Node* pCur = pRoot;        if (NULL == pCur)            return 0;        if (pCur->_pLeft == NULL&&pCur->_pRight == NULL)      //如果左右子树都为空,则返回1              return 1;        return Leaf(pCur->_pLeft) + Leaf(pCur->_pRight);    }/*非递归*/     size_t Leaf(Node* pRoot)    {        size_t index = 0;        Node* pCur = pRoot;        stack<Node*> s;        while (pCur || !s.empty())        {            while (pCur)            {                //如果左右子树都为空,则为叶子结点                  if (pCur->_pLeft == NULL&&pCur->_pRight == NULL)                    index++;                s.push(pCur);                pCur = pCur->_pLeft;            }            Node* pPre = s.top();            s.pop();            pCur = pPre ->_pRight;        }        return index;    }·········求结点个数/*递归*/    size_t Size(Node* pRoot)    {        if (pRoot == NULL)            return 0;        return 1 + Size(pRoot->_pLeft) + Size(pRoot->_pRight);    }/*非递归*/       size_t Size(Node* pRoot)    {        size_t index = 0;        Node* pCur = pRoot;        stack<Node*> s;        while (pCur || !s.empty())        {            while (pCur)            {                index++;        //遍历一个结点就让count++                  s.push(pCur);                pCur = pCur->_pLeft;            }            Node * top = s.top();            s.pop();            pCur = top->_pRight;        }        return index;    }········树的深度/*递归*/        size_t Depth(Node* pRoot)    {        Node* pCur = pRoot;        if (NULL == pCur)            return 0;        return 1 + (Depth(pCur->_pLeft) > Depth(pCur->_pRight)            ? Depth(pCur->_pLeft) : Depth(pCur->_pRight));    }/*非递归*/        size_t Depth(Node* pRoot)    {        if (pRoot == NULL)            return 0;        queue<Node*> q;        size_t deep = 0;        size_t  NodeNum = 1;      //统计有多少数据入过队          size_t  LeveLast = 1;      //标记正在访问的这层的最后一个数据的序号          size_t  VisitNum = 0;       //统计已经出队的数据的个数          q.push(pRoot);        while (!q.empty())        {            Node* pCur = q.front();            q.pop();            VisitNum++;            if (NULL != pCur->_pLeft)            {                q.push(pCur->_pLeft);                NodeNum++;            }            if (NULL != pCur->_pRight)            {                q.push(pCur->_pRight);                NodeNum++;            }            //如果以出队的个数等于这一层的最后一个数据的序号              if (LeveLast == VisitNum)            {                deep++;                //访问完一层就让深度加一                  LeveLast = NodeNum;    //更新到下一层的最后一个数据的位置              }        }        return deep;    }

创建好之后让我么来测试一下,首先测试递归版本的二叉树
测试代码如下

void FunTest(){    int array[] = { 1, 2, 3, '#', 4, '#', '#', 5, 6, '#', '#', 7 };    BinaryTree<int> t(array, sizeof(array) / sizeof(array[0]), '#');    cout << t._Leaf() << endl;    cout << t._Size() << endl;    cout << t._Depth() << endl;    t._PreOder();    t._InOder();    t._BackOder();}int main(){    FunTest();    return 0;}

输出结果为
这里写图片描述

接下来是非递归版本的二叉树
测试代码如下

void FunTest(){    int arr[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };    BinaryTree<int> t(arr, sizeof(arr) / sizeof(arr[0]), '#');    t._PrevOder();    t._InOder();    t._BackOder();    cout << t._Leaf() << endl;    cout << t._Size() << endl;    cout << t._Depth() << endl;}int main(){    FunTest();    system("pause");    return 0;}

输出结果为
这里写图片描述

以上就是二叉树的创建及基本操作

0 0
原创粉丝点击