二叉树是一种应用广泛的数据结构,例如操作系统中子进程与父进程,面向对象编程中的继承关系,网络拓扑结构等都有树的影子。

  二叉树最常见的操作:1)先序、中序、后序遍历各节点;2)已知先序和中序或者已知中序和后序,还原出唯一的二叉树;

  这里用C代码演示先序、中序和后序三种遍历:

  代码1 BinaryTree.c

  

/*************************************************************************

* Project:
* Function:二叉树三种遍历方式演示

*************************************************************************
* : magc $
* : magc@gmail.com $
*************************************************************************
*
* Copyright 2011 by magc
*
***********************************************************************
*/

#include "BinaryTree.h"

/*****************************************

创建一个二叉树,如下:

A
/ \
C B
/ / \
D F G
\
E

****************************************
*/

struct BTreeNode* initialTree()
{
//根指针
//二叉树作参数,只需要传递一个根指针即可,效率高,内存省
pTREE_NODE pRoot = (pTREE_NODE)malloc(sizeof(BTREE_NODE));
pRoot->data = 'A';
pRoot->pLChild = NULL;
pRoot->pRChild = NULL;
pTREE_NODE pB = CreteaNode(pRoot ,'B','R');
pTREE_NODE pC = CreteaNode(pRoot ,'C','L');
pTREE_NODE pD = CreteaNode(pC ,'D','L');
CreteaNode(pD ,'E','R');
CreteaNode(pB ,'F','L');
CreteaNode(pB ,'G','R');
printf("二叉树创建完毕!\n");
return pRoot;
}
/**********************************************
创建新节点
参数1:父节点指针
参数2:节点数据
参数3:子节点类型('R'表示右子树,'L'表示左子树)
返回值:新子节点指针
*********************************************
*/
pTREE_NODE CreteaNode(pTREE_NODE ptr ,char value , char child)
{

pTREE_NODE ptmp = (pTREE_NODE)malloc(sizeof(BTREE_NODE));
if(NULL == ptmp)
{
printf("内存分配失败\n");
exit(-1);
}
ptmp->data = value;
ptmp->pRChild = NULL;
ptmp->pLChild = NULL;
if('R' == child)
{
ptr->pRChild = ptmp;

}else if('L' == child)
{
ptr->pLChild = ptmp;
}

return ptmp;

}
/**********************
先序遍历
*********************
*/
void preTraverseBTree(pTREE_NODE ptr)
{
//先访问根节点
if(NULL != ptr)
printf("%c",ptr->data);
//然后先序访问左子树
if(NULL != ptr->pLChild)
preTraverseBTree(ptr->pLChild);
//最后先序访问右子树
if(NULL != ptr->pRChild)
preTraverseBTree(ptr->pRChild);
}

/**********************
中序遍历
*********************
*/
void midTraverseBTree(pTREE_NODE ptr)
{
//先中序访问左子树
if(NULL != ptr->pLChild)
midTraverseBTree(ptr->pLChild);
//然后访问根节点
if(NULL != ptr)
printf("%c",ptr->data);
//最后访问右子树
if(NULL != ptr->pRChild)
midTraverseBTree(ptr->pRChild);

}

/**********************
后序遍历
*********************
*/
void behindTraverseBTree(pTREE_NODE ptr)
{
//先后序访问左子树
if(NULL != ptr->pLChild)
behindTraverseBTree(ptr->pLChild);
//然后后序访问右子树
if(NULL != ptr->pRChild)
behindTraverseBTree(ptr->pRChild);
//最后访问根节点
if(NULL != ptr)
printf("%c",ptr->data);

}

  代码2 BinaryTree.h

#include <stdio.h>
#include <stdlib.h>

/*******************
定义二叉树节点

******************
*/
typedef struct BTreeNode
{
char data;
struct BTreeNode *pLChild ;
struct BTreeNode *pRChild ;

}BTREE_NODE,*pTREE_NODE;

struct BTreeNode* initialTree();
pTREE_NODE CreteaNode(pTREE_NODE ptr ,char value , char child);
void preTraverseBTree(pTREE_NODE ptr);
void behindTraverseBTree(pTREE_NODE ptr);
void midTraverseBTree(pTREE_NODE ptr);

代码3 main.c

#include <stdio.h>
#include <stdlib.h>
#include "BinaryTree.h"
int main()
{
printf("二叉树遍历演示!\n");
pTREE_NODE pt = NULL;
pt = initialTree();
printf("先序遍历:\n");
preTraverseBTree(pt);
printf("\n中序遍历:\n");
midTraverseBTree(pt);
printf("\n后序遍历:\n");
behindTraverseBTree(pt);

return 0;
}

  运行效果:

 

小结:

1)先序、中序、后序三种遍历,区别就在于访问根节点、左子树和右子树的顺序不同,并应用递归思想实现遍历过程;

2)二叉树是树应用的最常见形式,它的相关操作有必须熟练于心;

3)理解树的结构实现,节点是struct定义,节点之间的关系用两个指针域来实现;注意每次新建一个节点后,先要将两个指针域置NULL