前些天看数据结构,看到了二叉树的相关操作,我觉得,链表搞透彻了,这些东西都不是问题,还有栈、队列之类的,都是基于结构体和指针,其原理和链表相差无几,接下来来分享一下二叉树的创建以及各种遍历方法:
二叉树简介
二叉树的第层至多拥有个节点数;深度为的二叉树至多总共有个节点数(定义根节点所在深度),而总计拥有节点数匹配的,称为“满二叉树”;
深度为有个节点的二叉树,当且仅当其中的每一节点,都可以和同样深度的满二叉树,序号为1到的节点一对一对应时,称为“完全二叉树”;
二叉树创建
首先定义结构体:
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;
}
希望对大家的学习有一定的帮助,欢迎大家批评指正~