关于二叉树的遍历问题

	二叉树表示的是一个节点最多有两个子树,叫做左子树和右子树。那么我们遍历的情况,一共有四种情况了:根左右(前序),
左根右(中序),左右根(后序),以及层次遍历。主要说一下前序遍历,中序遍历,以及后序遍历。前序遍历正如上边的描
述一样是根左右,所以首先输出的是根节点的数据,然后再输出左子树的数据,最后输出右子树的数据。拿一个二叉树来说明一下:
								1
							  /    \
						     2      3
						    / \    /  \
						   4   5  6    7

那么我们按照根左右的遍历顺序来进行输出的话,首先读到的第一个数据是根1,所以此时输出1,然后去输出它的左子树,发现它
的左子树也是一个树的根节点,所以我们继续把2输出,然后我们去输出这个树的左子树,发现这个左子树也是一个根节点,但是
它没有左子树和右子树而已。所以我们直接输出其根节点4,然后我们发现这个左子树的根节点没有了,左子树没有,右子树也没有,
然后返回到上一层2,去访问其右子树,因为右子树肯定也是一个根节点,所以直接输出5,然后发现5没有左子树,右子树,所以我
们遍历完2的所有的左子树和右子树了。然后我们返回到1,其实这个时候我们遍历完根1的左边的子树了。然后我们去遍历根1的右
子树。发现一个3,其肯定也是一个根,然后我们继续按照根左右的顺序发现其左子树是6,然后输出6。发现6既没有左子树也没
有右子树,那么我们遍历完3的所有左边的树了。然后我们去遍历3的右边的树,然后发现是7,直接输出,因为其肯定也是一个根,
发现7没有左子树也没有右子树了,所以此时我们遍历完3的所有的右子树了。所以这个时候我们遍历完1的所有右子树了。所以遍
历完整个树了:
					其前序遍历输出为:1,2,4,5,3,6,7:
 //C++程序
 template<typename T> void preOrder(binaryTreeNode<T> *t){
 31     if(t != NULL){
 32         //根左右
 33         visit(t);//先输出本身根
 34         preOrder(t->leftChild);//左
 35         preOrder(t->rightChild);//右
 36     }
 37 }

	然后我们继续说明一下中序遍历:左根右。左根右,其实也顾名思义,就是先输出左子树,然后在输出根节点,再输出其右子树。
那么按照这个思路,我们遍历上面的二叉树。首先发现根1,因为其为根,不是左子树,所以继续往下找,找其左子树发现是2,发
现2还有左子树4,然后跳到4,发现4没有左子树,所以此时这个4就是最底下的一个左子树了,所以我们输出左子树4,然后去找其
根发现是2,所以我们输出2(因为是根左右)。然后我们去找2的右子树,发现是5,然后我们继续按照左根右的顺序去遍历5这个
根,因为5没有左子树所以直接输出根5,然后去找其右子树,发现也没有右子树,所以返回到根2这个时候表示根1的左子树已经
遍历完了,所以我们直接输出根1,然后我们去遍历根1的右子树,因为发现右子树是3,因为其肯定也是一个根,我们继续按照左
根右的遍历方式去遍历,发现3的左子树是6,因为6也是根,所以我们继续按照左根右的方法去遍历,发现其左子树是NULL,然后
表示我们已经遍历完根6的左子树了,所以我们要输出根了就是6。然后接着去遍历其右子树,发现也是NULL,所以此时返回到上
一个节点是3表示此时根3的左节点也遍历完了,那么我们继续去遍历3的右节点。发现右节点是7,因为7肯定也是一个根节点,所
以我们继续去按照左根右的方法去遍历,发现其左子树是NULL,所以表示遍历完其左子树,然后输出根7,然后我们遍历其右子树,
发现是NULL,所以我们直接返回到3节点,这个时候表示我们左根右已经完全了。所以我们的中序输出是:
					4251637
//C++程序
 40 template<typename T> void inOrder(binaryTreeNode<T> *t){
 41     if(t != NULL){
 42         inOrder(t->leftChild);
 43         visit(t);
 44         inOrder(t->rightChild);
 45     }
 46 }

	后序遍历:左右根。遍历上面的树,那么首先遍历左子树,所以我们直接找到了4,然后发现其没左子树,然后去遍历它的右子树,
	发现其也没有右子树,所以直接输出根4,然后返回到其上一个根节点是2,继续去遍历其右子树,找到5,发现5既没有左子树也
	没有右子树,所以直接输出5。表示其这个根的右子树也遍历完了,返回到2,表示其左右子树都遍历完了,我们直接输出2(根)。
	然后返回到根1,去查找右子树。然后继续按照左右根的顺序找到右边的树的左子树6,发现其左右子树都没有,所以直接输出
	根6,然后返回到其父根3,然后继续查找其父根的右子树7,继续按照左右根的顺序去遍历7的左右子树,发现没有左右子树,直
	接输出7然后返回到其父根3,表示父根3的左右子树遍历完了,然后返回到根1,表示根1的左右子树也遍历完了,所以直接输出1。
	所以后序遍历的结果是:
							4526731
 47 //后序遍历的顺序是:
 48 //左右根
 49 template<typename T> void postOrder(binaryTreeNode<T> *t){
 50     if(t != NULL){
 51         postOrder(t->leftChild);
 52         postOrder(t->rightChild);
 53         visit(t);
 54     }
 55 } 
	层次遍历其实一层一层的输出,这个没啥好说的,直接上程序:
 69 //层次遍历
 70 //                      1
 71 //                    /   \
 72 //                   2     3
 73 //                  / \   /  \
 74 //                 4   5 6    7
 75 //
 76 //
 77 //其实就是每一个节点的孩子都入队列,那么在第一层的时候,可以把左孩子和有孩子入队列也就是2,3
 78 //然后我们就是继续进来先把2输出,然后把2的左右孩子入队列那么队列中就是2345然后2出队,接着把3的
 79 //左右孩子入队列,也就是34567,然后把3出队里,接着因为4的左右孩子没有,所以不需要入队列,接着我们
 80 //继续输出5,一直进行到队列为空
 81 template<typename T> void levelOrder(binaryTreeNode<T> *t){
 82     std::queue<binaryTreeNode<T> *> q;
 83     while(t != NULL){//一层一层的遍历这个
 84         visit(t);//首先访问该节点
 85         if(t->leftChild != NULL)
 86             q.push(t->leftChild);
 87         if(t->rightChild != NULL)
 88             q.push(t->rightChild);
 89         try{
 90             t = q.top();
 91             throw illegalValue("the queue is empty");
 92         }catch(illegalValue queueEmpty){
 93             return;
 94         }
 95         q.pop();
 96     }
 97 } 
	最后说一下,如何根据前序和中序来构造一个二叉树。首先我们要明白一个点:前序是只要是节点我就输出,因为任何一个节点都是
	一个根节点。所以前序得到的第一个节点就是根节点,然后接着就是其左子树的根节点,然后就是其左子树的左子树。也就是说我
	们得到的前序遍历的基本上都是从左往右看得到的结果的。就比如上面的是1245367。而中序遍历得到的第一个节点是最左
	边的节点,然后接着是其根节点,然后是其右子树的最左边的子树。所以我们可以知道根节点肯定是在遍历顺序中的中间的,然后
	根节点的左子树又是在遍历输出的左半边的中间的。其实就是按照把根节点挨个插入到每次遍历的中间的,比如说上面的结果是:
					4 2 5 1 6 3 7
那么我这个遍历顺序的中间的肯定是根节点,也就是1肯定是根节点,然后1左边的肯定是根节点的所有的左子树,然后1后边的全是根节点的右边的树节点。然后根据这个特性。我们可以根据前序遍历的结果来构造唯一的一个二叉树:
				前序:		1 2 4 5 3 6 7
				中序:		4 2 5 1 6 3 7
首先我们根据前序得到的第一个节点是1,也就是根节点是1,然后在中序的中间位置找到1,这个时候可以得出4 2 5是根节点1的左边的所有树
节点,然后3 6 7表示的是根节点1的右边的所有树。然后我们继续查找前序发现是2,这个表示的是根的左子树,因为我们通过中序遍历发现根
的左边是有好几个树节点的,也就是说2是其根节点的左子树,然后我们发现2是在中序遍历中425的中间,所以表示2也有左右子树,然后继续
去查找前序,发现是4,然后发现2的左子树只有一个所以肯定的是2的左子树是4,然后因为根节点1和其左子树节点2之间只有一个树节点是5,
因为5是在2的右边,所以2的右子树肯定是5了,就构成了现在这个结构:
										1
									   /
									  2
									 /  \
									4    5
然后我们继续去查看前序,发现是3,然后在中序中发现3是在6和7之间,其实就是表明根节点的右子树3,又有左子树和右子树,3的左子树是
6,右子树是7这样我们就构造出了完整的二叉树了
										1
									   /  \
									  2    3
									 / \  /  \      
									4   56    7
其实前序和中序来唯一构造一个二叉树,主要是利用中序表示的中点是根节点,然后其左边是其所有的左子树,然后右边是其所有的右子树。
然后前序是用来确定其根节点的。
	根据后序和中序其实也是同样的道理:
					中序:	4 2 5 1 6 3 7
					后序:	4 5 2 6 7 3 1
首先因为后序遍历的时候最后输出的是最开始的根节点,也就是1,所以在中序中找到1,发现1有左边的树4,2,5,也有右子树6 3 7。然后
根据后序的特性倒数第二个肯定是根节点的右子树,也就是3肯定是根节点的右子树。我们去中序遍历的结果中找到3在6和7中间,所以发现
6是3的左子树,然后7是3的右子树。所以构造好
了右边的树
										1
										 \
										  3
										 /  \
										6    7
然后我们继续去看后序遍历的结果,发现确实是1 3 7 6倒序这种的,说明是对的,然后2肯定是根节点1的左子树,去中序中查找发现2在4和5
之间,所以得出2的左右子树是4和5,所以构造出来:
										1
									   /  \
									  2    3
									 / \  /  \      
									4   56    7

其实我们发现后序遍历的输出最后一个肯定是根节点1,然后倒数第二个肯定是其右子树,然后倒数第三个肯定是其右子树
3的右子树的根节点。最后输出的一个肯定是其最左边的一个节点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值