树
定义:
1.有且仅有一个称为根的节点
2.有若干个互不相交的子树,这些子树本身也是一棵树
通俗定义:
1.树是由节点和边组成
2.每个节点只有一个父节点但可以有多个子节点
3.但有一个节点例外,该节点没有父节点,此节点称为根节点
专业术语:节点 父节点 子节点 子孙 堂兄弟
深度:从根节点到最底层节点的层数称之为深度,根节点是第一层
叶子节点:没有子节点的节点
非终端节点:实际就是非叶子节点,既有子节点的节点
度:子节点的个数(子节点度最大的为树的度)
树的分类
一般树:任意一个节点的子节点的个数都不受限制
二叉树:任意一个节点的子节点个数最多为两个,且子节点的位置不可更改
分类:
一般二叉树
满二叉树:在不增加树的层数的前提下,无法再多添 加一个节点的二叉树
完全二叉树:如果只删除满二叉树最底层最右边的连续若干个节点
(满二叉树是完全二叉树的一个特列)
森林:n个互不相交的数的集合
树的存储:
二叉树的存储:
连续存储【完全二叉树】
【优点】:查找某个节点的父节点和子节点(可以判断有没有子节点)
【缺点】:耗用内存空间大
链式存储
我们存普通树,首先将其变成完全二叉树在进行存储。
一般树的存储:双亲表示法:求父节点比较方便
孩子表示法:求子节点比较方便
双亲孩子表示法:求两个都比较方便
二叉树表示法:将普通树转换成二叉树来存储,既设法保证任意一个节点的
左指针域指向他的第一个孩子,右指针域指向他的兄弟
森林的存储
先把森林转换成二叉树,在存储二叉树
二叉树的操作:
遍历:
先序遍历:先访问根节点,再先序访问左子树,再先序访问右子树。【先访问根节点】
中序遍历:中序遍历左子树,再访问根节点,在中序遍历右子树。【中间访问根节点】
后序遍历:中序遍历左子树,在中序遍历右子树,再访问根节点。【最后访问根节点】
已知两种遍历序列,求原始二叉树:
只能通过先序中序或中序后序,才能还原二叉树。
应用:树的数据库中数据组织一种重要形式
操作系统子父进程的关系就是一棵树
面向对象语言中类的继承关系就是一颗树
赫夫曼树
链式二叉树的遍历
#include <stdio.h>
# include <malloc.h>
struct BTNode
{
char data;
struct BTNode* pLchild;
struct BTNode* pRchild;
};
struct BTNode* CreatBTree() {
struct BTNode* pA = (struct BTNode*)malloc(sizeof(struct BTNode));
struct BTNode* pB = (struct BTNode*)malloc(sizeof(struct BTNode));
struct BTNode* pC = (struct BTNode*)malloc(sizeof(struct BTNode));
struct BTNode* pD = (struct BTNode*)malloc(sizeof(struct BTNode));
struct BTNode* pE = (struct BTNode*)malloc(sizeof(struct BTNode));
pA->data = 'A';
pB->data = 'B';
pC->data = 'C';
pD->data = 'D';
pE->data = 'E';
pA->pLchild = pB;
pA->pRchild = pC;
pB->pLchild = pB->pRchild = NULL;
pC->pLchild = pD;
pC->pRchild = pD->pLchild = NULL;
pD->pRchild = pE;
pE->pLchild = pE->pRchild = NULL;
return pA;
}
//void PostTraverBTree(struct BTNode* );
void PreTraverBTree(struct BTNode* p) {
if (p != NULL) {
printf("%c\n", p->data);
}
if (p->pLchild != NULL) {
PreTraverBTree(p->pLchild);//递归思想
}
if (p->pRchild != NULL) {
PreTraverBTree(p->pRchild);//递归思想
}
}
void InTraverBTree(struct BTNode* p) {
if (p != NULL) {
if (p->pLchild != NULL) {
InTraverBTree(p->pLchild);//递归思想
}
printf("%c\n", p->data);
if (p->pRchild != NULL) {
InTraverBTree(p->pRchild);//递归思想
}
}
}
void PostTraveraBTree(struct BTNode* p) {
if (p != NULL) {
if (p->pLchild != NULL) {
PostTraveraBTree(p->pLchild);//递归思想
}
if (p->pRchild != NULL) {
PostTraveraBTree(p->pRchild);//递归思想
}
printf("%c\n", p->data);
}
}
void main()
{
struct BTNode* p = CreatBTree();
// PreTraverBTree(p);
// InTraverBTree(p);
PostTraveraBTree(p);
}