二叉树的创建及各种遍历

前些天看数据结构,看到了二叉树的相关操作,我觉得,链表搞透彻了,这些东西都不是问题,还有栈、队列之类的,都是基于结构体和指针,其原理和链表相差无几,接下来来分享一下二叉树的创建以及各种遍历方法:

二叉树简介

来源于维基百科

二叉树(英语:Binary tree)是每个节点最多只有两个分支(不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”和“右子树”。二叉树的分支具有左右次序,不能颠倒。

二叉树的第i层至多拥有2^{i-1}个节点数;深度为k的二叉树至多总共有{\displaystyle 2^{\begin{aligned}k+1\end{aligned}}-1}个节点数(定义根节点所在深度{\displaystyle k_{0}=0}),而总计拥有节点数匹配的,称为“满二叉树”;

深度为kn个节点的二叉树,当且仅当其中的每一节点,都可以和同样深度k的满二叉树,序号为1到n的节点一对一对应时,称为“完全二叉树”;

二叉树创建

首先定义结构体:

typedef struct Tree
{
	int data;                         //    数据域
	struct Tree *left, *right;        //    左孩子、右孩子
}Tree;
接着采用递归的方法进行创建、以先序遍历的方法,附上代码:
void create ( Tree* &T)			
	int n;
	scanf ( "%d", &n );              //    输入节点数据
	if ( n == 0 )                    //    也可以改成其他的,这里仅作为空节点的标志
	{
		T = NULL;
	} 
	else 
	{
		T = new Tree;
		T -> data = n;
		create ( T -> left );    //    递归创建左孩子
		create ( T -> right );   //    递归创建右孩子
	}
}
直到补全了所有的节点(无孩子的节点用空节点,这里是0来表示)

这样一个先序遍历创建的二叉树就建立好了,紧接着就是遍历了,通过遍历可以处理一些基本的操作(增、删、改、查);

二叉树的遍历分为先序遍历、中序遍历、后序遍历以及层次遍历:

来源于维基百科

先序遍历:
先访问根节点、如果有左孩子,继续访问左孩子,然后将左孩子当作下一个根节点继续重复访问,遇到无左孩子(左孩子为空节点)时开始访问其根节点的右孩子;直到所有的否访问完,退出(图中顺序:2->7->2->6->5->11->5->9->4)。

中序遍历:
首先判断是否为空二叉树,如果不是,判断是否有左孩子,如果有访问左孩子,如何继续循环判断,如果没有,开始访问相对根节点(即该节点无孩子,访问该节点的父节点),如何访问右孩子;直到遍历结束退出(途中顺序:2->7->5->6->11->2->5->9->4)。

后序遍历:
首先判断是否为空,然后判断是否有左孩子,如果有,访问左孩子,并将左孩子当作根节点继续重复,直到无左孩子时,访问其根节点的右孩子,最后访问根节点,直到遍历结束退出(图中顺序:2->5->11->6->7->4->9->5->2)

层次遍历:
层次遍历相对来说好理解一点,就是按行访问,第一行访问结束开始访问下一行,图中的顺序为2->7->5->2->6->9->5->11->4 我相信把访问顺序列出来就应该很容易就理解了。虽然好理解,但是实现起来却不容易;

其实先序中序后续听起来很复杂,弄懂了之后会发现特别简单,先序:跟、左、右;中序:左、根、右;后序:左、右、根;你可以这样理解:按什么顺序,就怎么访问根节点,先序就先访问根节点,中序的话,根节点就放到中间访问,后序就最后访问根节点;理解之后三种顺序搞出来一个,其他两个就So easy 了。
接下来放代码:

void out1 ( Tree* T )						//		先序遍历输出 
{
	if ( T )
	{
		printf ( "%d ", T -> data );                    //    先访问根节点
		out1 ( T -> left );
		out1 ( T -> right );
	}
}
void out2 ( Tree* T )						//	中序遍历输出 
{
	if ( T )
	{
		out2 ( T -> left );                            
		printf ( "%d ", T -> data );                    //    中间访问根节点
		out2 ( T -> right );
	}
}
void out3 ( Tree* T )						//		后序遍历输出 
{
	if ( T )
	{
		out3 ( T -> left );
		out3 ( T -> right );
		printf ( "%d ", T -> data );                       //    最后访问根节点
	} 
}

仔细观察不难发现:这三种顺序的代码仅仅是换了位置,代码本身并没有变化,这里的遍历以输出为例,增删改查都是同样的操作。

void out4 ( Tree* T )						//		层次遍历创建 
{
	int rear = -1, front = 0;
	Tree *nums[100];
	if ( !T )
	{
		return;
	}
	nums[front] = T;
	while ( front != rear )
	{
		printf ( "%d ",nums[++rear] -> data );
		if ( T -> left )
		{
			nums[++front] = T -> left;
		}
		if ( T -> right )
		{
			nums[++front] = T -> right; 
		}
		T = nums[rear+1];
	}
}  

怎么样,层次遍历还像你想的那么简单了吗?
参差遍历我觉得不用递归的简单些,而且层次遍历相对于先序中序后序来说不是重点,大家选择性的看一下,这里的代码中运用到栈的相关思想,我相信看到二叉树的情况下,栈应该都不成问题了。

最后主函数调用一下即可:

#include "stdio.h"

int main ( )
{
	printf ( "int 型,0 表示空节点:" );
	T = new Tree;
	create ( T );							
	printf ( "先序遍历输出:" );
	out1 ( T );
	printf ( "\n中序遍历输出:" );
	out2 ( T );
	printf ( "\n后序遍历输出:" );
	out3 ( T );
	printf ( "\n层次遍历输出:" );
	out4 ( T );
	printf ( "\n" );
	return 0;
}
希望对大家的学习有一定的帮助,欢迎大家批评指正~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值