二叉树的建立与遍历

来源:互联网 发布:企业qq群发软件 编辑:程序博客网 时间:2024/06/03 16:23

        首先了解定义,二叉树是特殊的树。它的特点是每个子树都只有两个结点,即左孩子和右孩子。所以我们在定义一个二叉树的时候,要明确一个结点有两个指针和一个结点域。二叉树的建立有递归和非递归两种方法,本人比较偏爱递归,因为代码简单。其实刚开始的时候,我实在难以理解递归建立二叉树,但是慢慢的发现了递归的方便之处。他可以用几句简单的代码就直接实现了冗长复杂的操作过程。接下来介绍递归算法建立二叉树。

        二叉树的递归建立有三种方法(遍历也是一样的):先序、中序、后序。

       我直接用先序建立二叉树。

       第一步,先定义二叉树每一个结点的内容

       typedef strcut node      

     {

            struct node *lchild;//每一个子树都是一个新的树

    struct node *rchild;

            char data;

      }BiTreeNode,*Tree;


//递归法构建树

   void creatTree(Tree&T)   {char c;cin >> c;if (c == '#')T = NULL;else{T = new BiTreeNode;//若树不为空,则新开辟一个树。T->data = c;creatTree(T->lchild);//递归调用,每一次都是一个新的树。creatTree(T->rchild);}    }
这种方法就可以实现树的建立,而递归思想在这段代码里边的作用简直十分的强大。我们可以看出虽然这段代码只有短短的几行,但是运行时的功能却是十分的强大。这就是递归的好处。接下来再次用递归实现树的遍历。

树的遍历与树的构建是一样的分为先序、中序、后序。先区分一下这三种方法的区别:


         按照这样的顺序,我们就可以很清楚的遍历所有的子树。那么如何用代码实现呢?我们知道递归是这个问题烦人中心思想。所以我们可以直接利用递归不断调用本身去实现树的遍历。

先序遍历:

void FprintfTree(Tree T){if (T){cout << T->data;FprintfTree(T->lchild);FprintfTree(T->rchild);}}

中序遍历:

void LprintfTree(Tree T){if (T){LprintfTree(T->lchild);LprintfTree(T->rchild);cout << T->data;}}
后序遍历 :
void  MprintfTree(Tree T){if (T){MprintfTree(T->lchild);cout << T->data;MprintfTree(T->rchild);}}
全部的代码为:
#include<iostream>using namespace std;typedef struct node{struct node *lchild;struct node *rchild;char data;  }BiTreeNode,*Tree;//BiTreeNode是struct node的别名(BiTreeNode==node) //递归法创建树void creatTree(Tree&T){char c;cin >> c;if (c == '#')T = NULL;else{T = new BiTreeNode;T->data = c;creatTree(T->lchild);creatTree(T->rchild);}}//先序遍历void FprintfTree(Tree T){if (T){cout << T->data;FprintfTree(T->lchild);FprintfTree(T->rchild);}}//后序遍历void  MprintfTree(Tree T){if (T){MprintfTree(T->lchild);cout << T->data;MprintfTree(T->rchild);}}//中序遍历void LprintfTree(Tree T){if (T){LprintfTree(T->lchild);LprintfTree(T->rchild);cout << T->data;}}int main(){Tree T;cout << "please input a tree(every tree has two children,"<<endl<<"if someone has no,please instead '#'):" << endl;cout << "按先序遍历输入例如:ab#d##c#e##" << endl;creatTree(T);cout << endl << endl;cout << "前序遍历" << endl;FprintfTree(T);cout << endl;cout << endl << "中序遍历" << endl;MprintfTree(T);cout << endl;cout << endl << "后序遍历" << endl;LprintfTree(T);return 0;}


运行结果如上图所示。


总结:其实我们在建立和遍历链表的时候,有时候想的过于复杂了。我刚开始的时候就理解不了如何建立树结点的左孩子与右孩子。最后接触了递归,还是有点云里雾里。其实递归就是不断的调用自己本身,因为在刚开始的结构体中我们定义了树的结点。而且每一个子结点都是一个新的树结点。所以在不断调用的过程中就是不断的创建新树的过程。理解了递归之后也就理解了树的建立和遍历。而遍历中的先序中序和后序,也都是根据递归之后的简单代码。可能递归比较难以理解,但是真的相当好用。我们在建立的时候也要注意:如果有的结点没有左孩子或者没有右孩子,我们一般用‘#’代替。








原创粉丝点击