数据结构—树|二叉树|前序遍历、中序遍历、后序遍历【图解实现】
结构
二叉树的遍历
一、树
由于树有一个不包含回路的特点,因此树被赋予了许多特性,如下所示:
1、一棵树中任意的两个结点有且仅有唯一的一条路径连通
2、一棵树如果有n个结点,那么它一定恰好有n-1条边
3、在一棵树中加上一条边,将会构成一个回路
4、一棵树中有且仅有一个没有前驱的结点,即为根结点
通常情况下,我们在对树进行讨论的时候,将一棵树中的每个点称为结点:
根结点:没有父结点的结点
叶结点:没有子结点的结点
内部结点:一个结点既不是根结点也不是叶结点
每个结点有一个深度的概念,例如上图左边的树,4号结点深度是3。
二、二叉树
1. 基本概念
2. 二叉树的存储结构
特点:
1、每个结点最多有两颗子树
2、左子树和右子树是有顺序的,次序不能颠倒
3、即使某个结点只有一颗子树,也要区分左右子树
4、二叉树可为空,空的二叉树没有结点,非空二叉树有且仅有一个根节点
二叉树中有两种比较特殊的二叉树:满二叉树、完全二叉树,对于满二叉树和完全二叉树可以按照层次进行顺序存储。
满二叉树:二叉树中每个内部结点都存在左子树和右子树
满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。
满二叉树的严格定义:一颗深度为h且具有2h-1个结点的二叉树。
完全二叉树:
二叉树相关名词解释:
结点的度:结点拥有的子树数目
叶子结点:度为0的结点
分支结点:度不为0的结点
树的度:树中结点的最大的度
层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1
树的高度:树中结点的最大层次
二叉树基本性质:
性质1:在二叉树的第k层上至多有2k-1个结点(k>=1)
性质2:在深度为m的二叉树至多有2m-1个结点
性质3:对任意一颗二叉树,度为0的结点(即叶子结点)总是比度为2的结点多一个
性质4:具有n个结点的完全二叉树的深度至少为[log2n]+1,其中[log2n]表示log2n的整数部分
存储方式
实现代码:
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct node
{
char data;
struct node *lchild; /* 左子树 */
struct node *rchild; /* 右子树 */
}BiTNode, *BiTree;
void CreatBiTree (BiTree *T) /* BiTree *T等价于 struct node **T */
{
char ch;
scanf("%c", &ch);
if (ch == '#') /* 当遇到#时,令树的结点为NULL,从而结束该分支的递归 */
{
*T = NULL;
}
else
{
*T = (BiTree)malloc(sizeof(BiTNode));
if (*T == NULL)
{
printf("内存分配失败");
exit(0);
}
(*T)->data = ch; /* 生成结点 */
CreatBiTree(&(*T)->lchild); /* 构造左子树 */
CreatBiTree(&(*T)->rchild); /* 构造右子树 */
/* 这里需要注意的是->的优先级比&高,所以&(*T)->lchild得到的是lchild的地址 */
}
}
int main()
{
int level = 1;
BiTree t = NULL;
printf("以前序遍历方式输入二叉树\n");
CreatBiTree(&t); /* 传入指针的地址 */
}
上面的实现代码使用的是链表,代码采用的是以前序遍历方式输入二叉树,当输入“#”时,指针指向NULL,说明是该结点是叶结点。
三、二叉树的遍历(前序/中序/后序遍历)
顺序:访问根节点->前序遍历左子树->前序遍历右子树
/* 以递归方式 前序遍历二叉树 */
void PreOrderTraverse(BiTree t, int level)
{
if (t == NULL)
{
return ;
}
printf("data = %c level = %d\n ", t->data, level);
PreOrderTraverse(t->lchild, level + 1);
PreOrderTraverse(t->rchild, level + 1);
}
中序遍历:首先遍历左子树,然后访问根节点,最后遍历右子树(左->根->右)
顺序:中序遍历左子树->访问根节点->中序遍历右子树
/* 以递归方式 中序遍历二叉树 */
void PreOrderTraverse(BiTree t, int level)
{
if (t == NULL)
{
return ;
}
PreOrderTraverse(t->lchild, level + 1);
printf("data = %c level = %d\n ", t->data, level);
PreOrderTraverse(t->rchild, level + 1);
}
/* 以递归方式 后序遍历二叉树 */
void PreOrderTraverse(BiTree t, int level)
{
if (t == NULL)
{
return ;
}
PreOrderTraverse(t->lchild, level + 1);
PreOrderTraverse(t->rchild, level + 1);
printf("data = %c level = %d\n ", t->data, level);
}