1.树的概念
树是一种非线性结构(一对多的关系),一组数据除了一个节点(根节点,没有前驱节点)外,
其余的任意节点有且仅有零节点或多个节点,我们把这种特殊的关系,称为树状关系,俗称一对多的关系
2.生活中如何描述树状关系
公司的人员架构 家族的族谱 学校的组织
3.树的逻辑关系:
树是由若干个节点组成的分支,每个节点都有可能组成一颗树
1.节点的度: 节点拥有的子树的数量,称之为该节点的度,度为0的节点称为叶子节点或者终端节点
度不为0的节点称为分支节点或者是非终端节点
n1,n1,n2
2.节点的层次
从树根开始,根为第一层,根的孩子(子节点)为第二层,树中的节点最大的层次为树的深度或者高度
4.二叉树
二叉树它的特性是:每个节点最多只能挂两个节点,即二叉树中不存在度大于2的节点
并且二叉树有左右之分,分为左子树和右子树,切记,逻辑顺序不能颠倒
二叉树的特性:
1.空二叉树
2.只有一个根节点的二叉树
3只有左子树
4.只有右子树
5.完全二叉树
5.二叉树的性质
1.在二叉树的第i层,最多有2^(i-1)个节点
2.深度为k的二叉树最多有2^k - 1个节点
3.对于任意一棵二叉树,如果其终端节点数为n0,度为2的节点为n2,则有 n2 = n0-1
4.满二叉树 :一棵树深度为k,且具有满足2^k - 1,我们把它称为满二叉树,就是不能再插入任何节点
5.完全二叉树,要满足以下两个条件:
1.除去最后一层,则此树必定是满二叉树
2.最后一层的节点必须是依次从左往右编排,如果左边不排满,右边不能排
3.完全二叉树总结 : 完全二叉树是从内存的角度考量的,主要是为了节约空间
满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树
练习 : 节点数为699的完全二叉树的叶子节点的数量是多少?
提示 (1) 套用 n2 = n0 - 1的公式
(2) 节点数为奇数的完全二叉树不存在度为1(n1)的节点 即n1 = 0
1.699 = n0+n1+n2 // 699 = 度为0的节点+度为1的节点+度为2的节点
2.n2 = n0-1 ==》 n0 = n2 + 1
3.699 = 2n2+1+n1 又因为 n1为0 ==》 699 = 2n2+1
4.n2 = 349
5.因为 n2 = n0-1 所以 n0 = n2+1 = 349+1 = 350
6.二叉树的存储
存储结构: 既可以保存元素有保存的元素与元素之间的关系
1.顺序存储(一块连续的空间),需要将此树抽象成完全二叉树才能存放,否则无法描述他们之间的逻辑关系,弊端是浪费空间
#define MAX_LEN 1024
dataTpye BinTree[MAX_LEN];
2.链式存储
struct BiTNode
{
dataTpye data; // 数据域
struct BiTNode *lchild,*rchild;// 指针域,指向下一个节点
};
7.二叉树的遍历
如何按某条搜索路径进行查找对应的节点
1.先序遍历 : 根 左 右
2.中序遍历 : 左 根 右
3.后序遍历 : 左 右 根
1.先序 中序 后序遍历是以根节点为参考点
2.若"左"和"右"不是终端节点,则会进入递归遍历,每次都是访问"根",遇到节点为空的时候则进行回退(回溯)
8.二叉排序树又名二叉查找树
二叉排序树要么是空树,要么需要满足以下条件:
1.如果它们的左子树不为空,则左子树的数值一定比根节点的数值小
2.如果它们的右子树不为空,则右子树的数值一定比根节点的数值大
3.左子树或右子树的数值一定不能和根节点相等
9.二叉查找树程序实现:
typedef char dataTpye;
struct struct BiTNode
{
dataTpye data; // 数据域
struct BiTNode *lchild,*rchild;// 指针域,指向下一个节点
};
// 将节点插入到二叉树中
struct BiTNode *Insert_Node(struct BiTNode *root,dataTpye data);
//遍历节点
// 先序遍历,中序遍历,后序遍历
具体代码:BinarySortTree.c
#include <stdio.h>
#include <stdlib.h>
//-----------------------------
typedef char dataTpye;
//-----------------------------
struct BiTNode
{
dataTpye data; // 数据域
struct BiTNode *lchild,*rchild;// 指针域,指向下一个节点
};
//-----------------------------
// 实现二叉排序树的数据插入
struct BiTNode *Insert_Node(struct BiTNode *root,dataTpye data)
{
// 定义遍历指针查找需要插入的位置
struct BiTNode *p = root;
// 创建新节点
struct BiTNode *pnew = malloc(sizeof(struct BiTNode));
if(pnew == NULL)
{
return NULL;
}
pnew->data = data;
pnew->lchild = NULL;
pnew->rchild = NULL;
// 如果二叉树没有节点
if(root == NULL) // 从无到有
{
root = pnew;
}
else // 二叉树有节点
{
// 遍历查找位置
while(p)
{
// 如果data的值大于根节点则,则右插
if(data > p->data)
{
if(p->rchild == NULL)
{
p->rchild = pnew;
break; // 插完就跑
}
else // 继续往右找
{
p = p->rchild;
}
}
else if(data < p->data) // 左插
{
if(p->lchild == NULL)
{
p->lchild = pnew;
break; // 插完就跑
}
else // 继续往左找
{
p = p->lchild;
}
}
else // data与根节点相等表示异常
{
printf("insert value error!\n");
break;
}
}
}
return root;
}
//-----------------------------
/* 先序实现遍历二叉排序树 */
void pre_order(struct BiTNode *root)
{
// 递归实现
// 退出条件
if(root == NULL)
{
return ;
}
// 根 左 右
// 根
printf("%c ",root->data);
// 左
pre_order(root->lchild);
// 右
pre_order(root->rchild);
}
/* 中序实现遍历二叉排序树 */
void mid_order(struct BiTNode *root)
{
// 递归实现
// 退出条件
if(root == NULL)
{
return ;
}
// 左 根 右
// 左
mid_order(root->lchild);
// 根
printf("%c ",root->data);
// 右
mid_order(root->rchild);
}
//-----------------------------
/* 后序实现遍历二叉排序树 */
void last_order(struct BiTNode *root)
{
// 递归实现
// 退出条件
if(root == NULL)
{
return ;
}
// 左 右 根
// 左
last_order(root->lchild);
// 右
last_order(root->rchild);
//根
printf("%c ",root->data);
}
//-----------------------------
/* 创建二叉排序树 按回车结束 */
struct BiTNode *create_sort_tree()
{
struct BiTNode *root = NULL;
// 不断的创建节点并插入到树中,按回车键结束
while(1)
{
dataTpye data = getchar();
if(data == '\n')
break; // 输入回车键跑路
// 将数据插入到树中,root因为是局部变量所以每次都得要跟一下树的状态
root = Insert_Node(root,data);
}
return root;
}
//-----------------------------
int main()
{
// 创建二叉排序树
struct BiTNode *root = create_sort_tree();
// 通过先序遍历打印结果
//pre_order(root);
// 中序遍历
//mid_order(root);
// 后序遍历
last_order(root);
printf("\n");
return 0;
}