二叉树是一种应用广泛的数据结构,例如操作系统中子进程与父进程,面向对象编程中的继承关系,网络拓扑结构等都有树的影子。
二叉树最常见的操作: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