笔记九:二叉树的创建、递归与非递归版前序、中序、后序查找、树高和节点判断

原创 2016年05月30日 16:23:25

代码:

#include<iostream>
#include<vector>
#include<stack>
using namespace std;


template<typename T>
struct binaryTreeNode{
    T element;
    binaryTreeNode<T>  *leftChild;      //左子树
    binaryTreeNode<T>  *rightChild;     //右子树
    binaryTreeNode() {
        leftChild = rightChild = NULL;
    }
    binaryTreeNode(const T& theElement)
    {
        element = theElement;
        leftChild = rightChild = NULL;
    }
    binaryTreeNode(const T&  theElement, binaryTreeNode *theLeftChild, binaryTreeNode *theRightChild)
    {
        element(theElement);
        leftChild = theLeftChild;
        rightChild = theRightChild;
    }
};

template <typename T>
class binaryTree{
public:
    virtual ~binaryTree() {}
    virtual bool empty() const = 0;
    virtual int size() const = 0;
    virtual void visit(T *) const = 0;
    virtual void InputBinaryNode() = 0;
    virtual void preCreateBinaryTree(T *&) = 0;

    /*virtual void preOrder(binaryTreeNode<T> *node) = 0;
    virtual void inOrder(binaryTreeNode<T> *node) = 0;
    virtual void postOrder(binaryTreeNode<T> *node) = 0;

    virtual void Iter_preOrder(binaryTreeNode<T> *node) = 0;
    virtual void Iter_inOrder(binaryTreeNode<T> *node) = 0;
    virtual void Iter_postOrder(binaryTreeNode<T> *node) = 0;*/
    virtual void preOrder(T *) = 0;
    virtual void inOrder(T *) = 0;
    virtual void postOrder(T *) = 0;

    virtual void Iter_preOrder(T *) = 0;
    virtual void Iter_inOrder(T *) = 0;
    virtual void Iter_postOrder(T *) = 0;


};

template<typename E>
class linkedBinaryTree : public binaryTree<binaryTreeNode<E> >
{
public:
    linkedBinaryTree(){ root = NULL; treeSize = 0; }
    ~linkedBinaryTree() {};
    bool empty() const { return treeSize == 0; }
    int size() const { return treeSize; }
    void visit(binaryTreeNode<E> *node) const;
    void InputBinaryNode();
    void preCreateBinaryTree(binaryTreeNode<E> *&node);
    int height(binaryTreeNode<E> *&node) const;

    void preOrder(binaryTreeNode<E> *node);
    void inOrder(binaryTreeNode<E> *node);
    void postOrder(binaryTreeNode<E> *node);

    void Iter_preOrder(binaryTreeNode<E> *node);
    void Iter_inOrder(binaryTreeNode<E> *node);
    void Iter_postOrder(binaryTreeNode<E> *node);


private:
    binaryTreeNode<E> *root;
    int treeSize;
    vector<E> vecNode;
};

template<typename E>
void linkedBinaryTree<E>::visit(binaryTreeNode<E> *node) const
{
    //访问节点*node, 仅输出element
    cout << node->element << " ";
}

template<typename E>
void linkedBinaryTree<E>::InputBinaryNode()
{
    E elem;
    cout << "!!!注意:(1)#表示空节点;(2)请在输入的字符串末尾加0,作为输入结束的标志!" << endl;
    while (cin >> elem && elem != '0')
    {
        vecNode.push_back(elem);
    }
}

template<typename E>
void linkedBinaryTree<E>::preCreateBinaryTree(binaryTreeNode<E> *&node)
{
    vector<E>::iterator it = vecNode.begin();
    if (it != vecNode.end())
    {
        if (*it == '#')
        {
            node = NULL;
            vecNode.erase(it);
        }
        else{
            node = new binaryTreeNode<E>(*it);  //生成根节点
            treeSize++;
            vecNode.erase(it);
            preCreateBinaryTree(node->leftChild);   //构造左子树
            preCreateBinaryTree(node->rightChild);  //构造右子树
        }
    }
    else{
        node = NULL;
    }
}

template<typename E>
int linkedBinaryTree<E>::height(binaryTreeNode<E> *&node) const
{
    if (!node)
    {
        return 0;
    }

    int hl = height(node->leftChild);   //左子树的高
    int hr = height(node->rightChild);  //右子树的高
    if (hl > hr)
    {
        return ++hl;
    }
    else{
        return ++hr;
    }

}

template<typename E>
void linkedBinaryTree<E>::preOrder(binaryTreeNode<E> *node)
{
    //根节点——左子树——右子树
    if (node)
    {
        visit(node);
        preOrder(node->leftChild);
        preOrder(node->rightChild);
    }

}

template<typename E>
void linkedBinaryTree<E>::inOrder(binaryTreeNode<E> *node)
{
    //左子树——根节点——右子树 
    if (node)
    {
        inOrder(node->leftChild);
        visit(node);
        inOrder(node->rightChild);
    }

}

template<typename E>
void linkedBinaryTree<E>::postOrder(binaryTreeNode<E> *node)
{
    //左子树——右子树——根节点
    if (node)
    {
        postOrder(node->leftChild);
        postOrder(node->rightChild);
        visit(node);
    }

}

template<typename E>
void linkedBinaryTree<E>::Iter_preOrder(binaryTreeNode<E> *node)
{
    stack<binaryTreeNode<E>* > stk;     //存储树节点
    binaryTreeNode<E> * currNode = node;
    while (currNode || (!stk.empty()))
    {
        if (currNode)
        {
            visit(currNode);            //访问根节点
            stk.push(currNode);
            currNode = currNode->leftChild; //遍历左子树
        }
        else{
            currNode = stk.top();       //节点入栈前已被访问,故无需再次访问
            stk.pop();
            currNode = currNode->rightChild;
        }
    }

}

template<typename E>
void linkedBinaryTree<E>::Iter_inOrder(binaryTreeNode<E> *node)
{
    stack<binaryTreeNode<E>* > stk;
    binaryTreeNode<E>* currNode = node;
    while (currNode || (!stk.empty()))
    {
        if (currNode)
        {
            stk.push(currNode);     //先将左子树全部压入栈
            currNode = currNode->leftChild;
        }
        else{
            currNode = stk.top();
            stk.pop();
            visit(currNode);        //访问根节点
            currNode = currNode->rightChild;
        }
    }
}

template<typename E>
void linkedBinaryTree<E>::Iter_postOrder(binaryTreeNode<E> *node)
{
    stack<binaryTreeNode<E>* > stk;
    binaryTreeNode<E>* currNode = node, *rightNode = node;
    while (currNode || (!stk.empty()))
    {
        if (currNode)
        {
            stk.push(currNode);     //遍历左子树
            currNode = currNode->leftChild;
        }
        else{
            currNode = stk.top();
            currNode = currNode->rightChild;    //遍历右子树
            if (!currNode)          //此时栈顶元素的左孩子、右孩子均为空,即为叶子节点
            {
                rightNode = stk.top();
                stk.pop();
                visit(rightNode);   //访问叶子节点
                //若刚被访问的叶子节点是此时栈顶元素的右孩子,则说明左、右子树均被遍历完
                //循环的目的是为了找到最终的父结点,当前所有已访问的节点是作为其左子树的节点而存在
                while ((!stk.empty()) && (stk.top()->rightChild == rightNode))
                {
                    rightNode = stk.top();  //由于该节点的右节点已被访问,说明完成了左右子树的遍历
                    stk.pop();
                    visit(rightNode);       //叶子节点已经被访问,则最后访问根节点
                }
                if (!stk.empty())           //刚被访问的是此时栈顶元素的左孩子,则右孩子还未入栈
                {
                    currNode = stk.top();
                    currNode = currNode->rightChild;
                }
            }
        }//else
    }
}

int main(int argc, char* argv[])
{
    linkedBinaryTree<char> LBT;
    binaryTreeNode<char>* root;
    LBT.InputBinaryNode();
    LBT.preCreateBinaryTree(root);
    cout << "二叉树的总节点数为:" << LBT.size() << endl;
    cout << "二叉树的高度为:"<< LBT.height(root) << endl;

    cout << "\n前序遍历二叉树(递归):" << endl;
    LBT.preOrder(root);
    cout << "\n中序遍历二叉树(递归):" << endl;
    LBT.inOrder(root);
    cout << "\n后序遍历二叉树(递归):" << endl;
    LBT.postOrder(root);

    cout << "\n\n前序遍历二叉树(非递归):" << endl;
    LBT.Iter_preOrder(root);
    cout << "\n中序遍历二叉树(非递归):" << endl;
    LBT.Iter_inOrder(root);
    cout << "\n后序遍历二叉树(非递归):" << endl;
    LBT.Iter_postOrder(root);

    return 0;
}

注:中间注释代码部分会造成,纯虚函数没有强制替代项的错误。

结果 :
这里写图片描述

注:上述代码是在我的旧文基础上改进的http://blog.csdn.net/u014033518/article/details/38844583

版权声明:本文为博主原创文章,未经博主允许不得转载。

笔记九:二叉树的创建、递归与非递归版前序、中序、后序查找、树高和节点判断

代码:#include #include #include using namespace std; template struct binaryTreeNode{ T element; ...
  • u014033518
  • u014033518
  • 2016年05月30日 16:23
  • 818

typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针

上面介绍得是我们常用的比较简单的typedef的用法,下面首先介绍一下函数指针。//定义一个指针变量p,根据形式1函数指针的形式 //我们可以知道他是指向一个参数为Int,返回类型为 //char的函...
  • u014221279
  • u014221279
  • 2016年03月25日 16:06
  • 5005

二叉树的创建与前序、中序和后序的递归与非递归调用

#include #include #include #include using namespace std; typedef char ElemType; class BiTNode { fr...
  • u014033518
  • u014033518
  • 2014年08月26日 10:51
  • 583

二叉树前序中序建立和后序中序建立

已知二叉树的前序序列和中序序列,求解树。 1、确定树的根节点。树根是当前树中所有元素在前序遍历中最先出现的元素。 2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边...
  • LsMrSUN
  • LsMrSUN
  • 2016年08月08日 10:59
  • 1982

【工程】二叉树已知前序/中序的顺序,构造树的递归等实现

文章中的二叉树原型为 《Data Structures, Algorithms, & Applications in C++》, 1nd Edition中的树类。 要求在源文件的基础上 实现以下三个...
  • mig_davidli
  • mig_davidli
  • 2013年04月27日 19:31
  • 1259

二叉树之线索链表

二叉树的线索链表的Java实现
  • u011677050
  • u011677050
  • 2016年12月02日 18:21
  • 1214

树的学习——(递归构建二叉树、递归非递归前序中序后序遍历二叉树、根据前序序列、中序序列构建二叉树)

前言 最近两个星期一直都在断断续续的学习二叉树的数据结构,昨晚突然有点融汇贯通的感觉,这里记录一下吧 题目要求 给定前序序列,abc##de#g##f###,构建二叉树,并且用递归和非递归两种方法...
  • zinss26914
  • zinss26914
  • 2012年12月29日 10:46
  • 7660

二叉树的创建 先序 中序 后续 递归和非递归遍历

二叉树 递归非递归遍历 总结
  • u011561690
  • u011561690
  • 2015年04月15日 19:00
  • 876

数据结构——二叉树1(c++)

数据结构——二叉树1(c++)
  • cckevincyh
  • cckevincyh
  • 2015年06月21日 17:30
  • 456

typedef void(*Fun)(void);

今天在SDK中看到了这么个写法: typedef void(CALLBACK *DisplayCBFun)( long nPort, char *pBuf, long n...
  • bigpudding24
  • bigpudding24
  • 2016年02月25日 18:14
  • 948
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:笔记九:二叉树的创建、递归与非递归版前序、中序、后序查找、树高和节点判断
举报原因:
原因补充:

(最多只允许输入30个字)