数据结构分为线性结构和非线性结构,而这次所讲的树和二叉树为非线性结构。
对于树和二叉树的理解,运用图能更好的让我们去直观的思考。在这之前,我先给大家提几个关于二叉树的慨念。
树:是由n个结点构成的集合。n = 0 的树为空树。
结点:包括一个元素及若干个指向其子树的分支。
结点的度:结点所拥有的子树的个数称为该结点的度。
叶节点:度为 0 的结点,也叫终端结点。
满二叉树:在一棵二叉树中所有分支都有左右孩子,并且所有叶子结点都在同一层。
完全二叉树:如果有一棵具有n个结点的二叉树的结构与满二叉树的前n个结点的结构相同,则称这样的二叉树叫完全二叉树。
总结一下:完全二叉树的最后一个结点的编号是n,则它的父结点的编号为[n/2],则叶子结点个数为n-[n/2]。
下面我把自己对识别完全二叉树的方法总结如下:
1,叶节点的层数之差不能大于 1 ,例如第五个图。
2,结点没有左孩子,一定不能有右孩子,例如第四个图。
3,满二叉树一定是完全二叉树。
二叉树的相关性质:
1,若规定根节点的层数为 0 ,则一颗非空二叉树的第 i 层最多有 2 的 i 次方个结点。
2,若规定只有根节点二叉树深度为 0 ,则深度为 k 的二叉树的最多节点数是 2 的 k + 1 次方减 1 。
3,对于一颗非空二叉树,如果叶节点个数为 n ,度为 2 的结点树为 m,则有 n = m + 1。
二叉树的遍历分为四种:前序遍历(DLR),中序遍历(LDR),后序遍历(LRD),层次遍历。
对于这个二叉树,
前序遍历(DLR):ABDECF
中序遍历(LDR):DBEAFC
后序遍历(LRD):DEBFCA
下面我介绍,二叉树的运用(递归实现),只要有创建二叉树,销毁二叉树,遍历二叉树,和打印二叉树的深度。程序如下:
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 // 存储空间初始分配量
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef char TElemType; // 字符型以空格符为空
TElemType Nil=' '; // 字符型以空格符为空
typedef struct BiTNode // 结点结构
{
TElemType data; // 结点数据
struct BiTNode *lchild,*rchild; // 左右孩子指针
}BiTNode,*BiTree;
Status InitBiTree(BiTree *T) // 构造空二叉树T
{
*T=NULL;
return OK;
}
void CreateBiTree(BiTree *T)
{
TElemType ch;
printf("请输入字符,输入#结束:\n"); //注意根据你想构造的二叉树的形状来输入相应数量的“#”
scanf("%c",&ch);
getchar();
if(ch=='#')
*T=NULL;
else
{
*T=(BiTree)malloc(sizeof(BiTNode));
if(!*T)
exit(OVERFLOW);
(*T)->data=ch; //生成根结点
CreateBiTree(&(*T)->lchild); // 构造左子树
CreateBiTree(&(*T)->rchild); // 构造右子树
}
}
Status BiTreeEmpty(BiTree T) // 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE
{
if(T)
return FALSE;
else
return TRUE;
}
int BiTreeDepth(BiTree T) // 初始条件: 二叉树T存在。操作结果: 返回T的深度
{
int i,j;
if(!T)
return 0; //当结点为空,返回0
if(T->lchild)
i = BiTreeDepth(T->lchild); //遍历左孩子,返回i值
else
i = 0;
if(T->rchild)
j = BiTreeDepth(T->rchild); //遍历右孩子,返回j值
else
j = 0;
return i>j?i+1:j+1;
}
TElemType Root(BiTree T) // 初始条件: 二叉树T存在。操作结果: 返回T的根
{
if(BiTreeEmpty(T))
return Nil;
else
return T->data;
}
void DestroyBiTree(BiTree *T) // 初始条件: 二叉树T存在。操作结果: 销毁二叉树T
{
if(*T)
{
if((*T)->lchild) // 有左孩子
DestroyBiTree(&(*T)->lchild); //销毁左孩子子树
if((*T)->rchild) // 有右孩子
DestroyBiTree(&(*T)->rchild); //销毁右孩子子树
free(*T); //释放根结点
*T=NULL; //空指针赋0
}
}
void PreOrderTraverse(BiTree T)
{
if(T==NULL)
return;
printf("%c",T->data); // 显示结点数据
PreOrderTraverse(T->lchild); //再先序遍历左子树
PreOrderTraverse(T->rchild); //最后先序遍历右子树
}
void InOrderTraverse(BiTree T)
{
if(T==NULL)
return;
InOrderTraverse(T->lchild); // 中序遍历左子树
printf("%c",T->data); //显示结点数据
InOrderTraverse(T->rchild); //最后中序遍历右子树
}
void PostOrderTraverse(BiTree T)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild); // 先后序遍历左子树
PostOrderTraverse(T->rchild); // 再后序遍历右子树
printf("%c",T->data); //显示结点数据
}
int main()
{
int i;
BiTree T;
TElemType e1;
InitBiTree(&T);
CreateBiTree(&T);
printf("构造空二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
e1=Root(T);
printf("\n前序遍历二叉树:");
PreOrderTraverse(T);
printf("\n中序遍历二叉树:");
InOrderTraverse(T);
printf("\n后序遍历二叉树:");
PostOrderTraverse(T);
printf("\n");
DestroyBiTree(&T);
printf("\n清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
return 0;
}
以上就是树二叉树的介绍,程序部分如有不懂,请加qq:2648636032,咨询。