树是一种一对多的逻辑结构,树的子树之间没有关系。

度:结点拥有的子树数量。

树的度:树中所有结点的度的最大值。

结点的深度:从根开始,自顶向下计数。

结点的高度:从叶结点开始,自底向上计数。

树的性质:①树的结点数等于所有结点的度数加1;②度为m的树中第i层上至多有mi-1个结点(i>=1);③度为h的m叉数至多有(mh-1)/(m-1)个结点;④具有n个结点的m叉树的最小高度为[logm(n(m-1)+1)]。

树的表示方法:

①双亲表示法(顺序表示法):根节点parent=-1

typedef char ElemType;
typedef struct TNode{
ElemType data; //结点数据
int parent; //该结点双亲在数组中的下标
}TNode; //结点数据类型
#define MaxSize 50
typedef struct{
TNode nodes[MaxSize]; //结点数组
int n; //结点数量
}Tree; //树的双亲表示结构

②孩子表示法:把每个孩子的孩子结点排列起来存储成一个单链表,n个结点就有n个单链表,n个单链表的头指针又存储在一个顺序表(数组)中

typedef char ElemType;
typedef struct CNode{
int child; //该孩子在表头数组的下标
struct CNode *next; //指向该结点的下一个孩子结点
}CNode,*Child; //孩子结点数据类型
typedef struct{
ElemType data; //结点数据域
Child firstchild; //指向该结点的第一个孩子结点
}TNode; //孩子结点数据类型
#define MaxSize 100
typedef struct{
TNode nodes[MaxSize]; //结点数据域
int n; //树中的结点个数
}Tree; //树的孩子表示结构

③孩子兄弟表示法:分别指向孩子结点和兄弟结点,其结点结构为:

 typedef char ElemType;
typedef struct CSNode{
ElemType data; //该结点的数据域
struct CSNode *firstchild,*rightsib; //指向该结点的第一个孩子结点和该结点的右兄弟结点
}CSNode; //孩子兄弟结点数据类型

二叉树:①每个结点最多有两棵子树;②左右子树有顺序。

二叉树的种类:①斜二叉树;②满二叉树;③完全二叉树。

满二叉树是绝对的等腰三角形,每一个非叶子结点都有两个子树,而完全二叉树的结点个数随意,只需满足其层序遍历的序号与满二叉树相同即可。

二叉树的顺序存储:用一组地址连续的存储单元依次自上向下,自左至右存储完全二叉树上的结点元素,非完全二叉树需在对应空缺编号处保留数组空位,这是一种极其浪费的存储方式。

二叉树的链式存储:

①二叉链表:两个指针指向左右孩子结点。其实现为:

typedef struct BiTNode{
ELemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

②三叉链表:在二叉链表的基础上添加一个指针指向双亲。

二叉树的遍历:按某种次序依次访问树中的每个结点,使得每个结点均被访问人一次,而且仅被访问一次。

有以下四种方法:

①先序遍历:a.访问根节点;b.先序遍历左子树;c.先序遍历右子树。

递归实现:

void PreOrder(BiTree T){
if(T!=NULL){
printf("%c",T->data); //访问根节点
PreOrder(T->lchild); //递归遍历左子树
PreOrder(T->rchild); //递归遍历右子树
}
}

非递归实现:在实现过程中利用了栈的思想

void PreOrder(BiTree b){
InitStack(s);
BiTree p=b; //工作指针p
while(p||!IsEmpty(s)){
while(p){
printf("%c",p->data);
Push(s,p); //进栈
p=p->lchild;
}
if(!IsEmpty(s)){
p=P0p(s);
p=p->rchild;
}
}
}

②中序遍历:a.中序遍历左子树;b.访问根节点;c.中序遍历右子树。

递归实现:

void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild); //递归遍历左子树
printf("%c",T->data); //访问根节点
InOrder(T->rchild); //递归遍历右子树
}
}

非递归实现:

void InOrder(BiTree b){
InitStack(s);
BiTree p=b;
while(p||!IsEmpty(s)){
while(p){
Push(s,p);
p=p->lchild;
}
p=Pop(s);
printf("%c",p->data);
p=p->rchild;
}
}

③后序遍历:a.后序遍历左子树;b.后序遍历右子树;c.访问根节点。

递归实现:

void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild); //递归遍历左子树
PostOrder(T->rchild); //递归遍历右子树
printf("%c",T->data); //访问根节点
}
}

非递归实现:

void PostOrder(BiTree b){
InitStack(s);
BiTree p=b,r=NULL; //工作指针p,辅助指针r
while(p||!IsEmpty(s)){ //从根节点到最左下角的左子树都入栈
if(p){
Push(s,p);
p=p->lchild;
}
else{
GetTop(s,p); //取栈顶,不是出栈
if(p->rchild&&p->rchild!=r) //如果栈顶存在右子树且未被访问过,就去访问
p=p->rchild;
else{ //不存在右子树或者被访问过,则出栈
Pop(s,p);
printf("%c",p->data);
r=p;
p=NULL;
}
}
}
}

④层序遍历:从上向下逐层遍历,在同一层中,从左到右对结点逐个访问。

层序遍历没有递归实现,只有非递归实现:其采用了队列的思想

void LevelOrder(BiTree b){
InitQueue(Q);
BiTree p;
EnQueue(Q,b); //根结点入队
while(!IsEmpty(Q)){ //队列不空循环
DeQueue(Q,p) //队头元素出队
printf("%c",p->data);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}

如何将一棵树转化成二叉树:①将同一结点的各个孩子用线串起来;②将每个结点的子树分支,从左往右,除了第一个以外全部删除。

将二叉树转化成树:将二叉树从上到下分层,并调节成水平方向,之后是正向转化的逆过程。

一个重要结论:n个结点的二叉链表,每一个结点都有指向左右孩子的结点指针,所以一共有2n个指针,而n个结点的二叉树一共有n-1条分支,也就是存在2n-(n-1)=n+1个空指针。

线索二叉树:指向前驱和后继的指针称为线索,加上线索的二叉链表就称为线索链表,相应的二叉树就称为线索二叉树。对二叉树以某种次序遍历使其变成线索二叉树的过程叫作线索化。

下面我们以中序遍历作为例子,实现线索二叉树,并对其遍历:

线索二叉树的实现:

typedef struct ThreadTNode{
ELemType data;
struct ThreadTNode *lchild,*rchild;
int ltag,rtag; //tag=0指向孩子,tag=1指向前驱或者后继
}ThreadTNode,*ThreadTree;
void InThread(ThreadTree &p,ThreadTree &pre){
//pre指向中序遍历时上一个刚刚访问过的结点,初值为NULL
if(p){
InThread(p->lchild,pre);
if(p->lchild==NULL){
p->lchild=pre;
p->ltag=;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->rchild=p;
pre->rtag=;
}
pre=p;
InThread(p->rchild,pre);
}
}

对线索二叉树进行中序遍历:

void InOrderTraverse(ThreadTree T){
ThreadTree p=T;
while(p){
while(p->ltag==) p=p->lchild;
printf("%c",p->data);
while(p->ltag==&&p->rchild){
p=p->rchild;
printf("%c",p->data);
}
p->rchild;
}
}

哈夫曼树中相关概念:

权:树中结点相关的数值;

路径长度:从树中某个结点到另一个结点之间的分支数目(经过的边数);

带权路径长度:从树的根结点到任意结点的路径长度与该结点权值的乘积;

树的带权路径长度:树中所有结点带权路径长度的和。

哈夫曼树的定义:含有n个带权叶子结点的二叉树中,其中带权路径长度最小的二叉树,也称为最优二叉树。

C语言数据结构基础学习笔记——树的更多相关文章

  1. C语言数据结构基础学习笔记——B树

    2-3树:是一种多路查找树,包含2结点和3结点两种结点,其所有叶子结点都在同一层次. 2结点:包含一个关键字和两个孩子(或没有孩子),其左孩子的值小于该结点,右孩子的值大于该结点. 3结点:包含两个关 ...

  2. C语言数据结构基础学习笔记——C语言基础

    抽象数据类型(ADT)是指一个数学模型以及定义在该模型上的一组操作,通常用(数据对象,数据关系,基本操作集)这样的三元组来表示抽象数据类型. 数据结构是相互之间存在一种或多种特定关系的数据元素的集合, ...

  3. C语言数据结构基础学习笔记——动态查找表

    动态查找表包括二叉排序树和二叉平衡树. 二叉排序树:也叫二叉搜索树,它或是一颗空树,或是具有以下性质的二叉树: ①若左子树不空,则左子树上所有结点的值均小于它的根结点的值: ②若右子树不空,则右子树上 ...

  4. C语言数据结构基础学习笔记——图

    图(G)由顶点集(V)和边集(E)组成,G=(V,E) 常用概念: ①V(G)表示图G中顶点的有限非空集,V永不为空: ②用|V|表示图G中顶点的个数,也称为图G的阶: ③E(G)表示图G中顶点之间关 ...

  5. C语言数据结构基础学习笔记——栈和队列

    之前我们学过了普通的线性表,接下来我们来了解一下两种特殊的线性表——栈和队列. 栈是只允许在一端进行插入或删除的线性表. 栈的顺序存储结构也叫作顺序栈,对于栈顶指针top,当栈为空栈时,top=-1: ...

  6. C语言数据结构基础学习笔记——静态查找表

    查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找. 查找表:用于查找的数据集合称为查找表,一般有以下操作:①查找是否在表中:②查找属性:③进行操作. 查找表又分为: ①静态查找表:只可以进行 ...

  7. C语言数据结构基础学习笔记——基础线性表

    线性表是指具有相同数据类型的n(n>=0)个数据元素的有限序列,它具有一个表头元素和一个表尾元素,并且每一个数据元素最多只有一个直接前驱和一个直接后继. 线性表的顺序存储也叫作顺序表,它的特性是 ...

  8. Oracle基础学习笔记

    Oracle基础学习笔记 最近找到一份实习工作,有点头疼的是,有阶段性考核,这...,实际想想看,大学期间只学过数据库原理,并没有针对某一数据库管理系统而系统的学习,这正好是一个机会,于是乎用了三天时 ...

  9. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

随机推荐

  1. caffe: c++11支持

    1)在Makefile中400行左右, CXXFLAGS += -MMD -MP  改成:CXXFLAGS += -MMD -MP -std=c++0x,好像还改了不少地方,有的是 -std=c++1 ...

  2. Feign源码解析系列-最佳实践

    前几篇准备写完feign的源码,这篇直接给出Feign的最佳实践,考虑到目前网上还没有一个比较好的实践解释,对于新使用spring cloud的同学会对微服务之间的依赖产生一些迷惑,也会走一些弯路.这 ...

  3. ubuntu下编译小知识点

    #改变编译器选项 SET(CMAKE_C_COMPILER"g++") #出现如下错误:添加C++11特性 #error: #error This file requires co ...

  4. Arcgis API for JS——普通分屏联动及二三维联动

    对于二三维联动,有多种方法进行实现,当时旧项目使用了当时能掌握的一种写法,在技能提升了这么多后当然要对这些写法做一个总结. 一.通过监听View上的鼠标事件变化来进行分屏联动(同一坐标系) (同理可以 ...

  5. java中的hashmap理解

    转自大神,以便以后翻阅http://www.cnblogs.com/whgk/p/6091316.html

  6. AX3298添加新sensor

    这是编译的工程目录. 1,先把sensor对应的驱动比如GC1034.c添加到工程.然后编译成库.会在res目录下生产sensor.bin文件 流程:编译后在debug目录生成 elf 文件AX329 ...

  7. iOS launchImage

    iOS launchImage https://stackoverflow.com/questions/34027270/ios-launch-screen-in-react-native 如何设置: ...

  8. Linux下RabbitMQ的安装 开机自启动

    1.官网下载地址 下载 RabbitMQ 和 erlang.我下载的是rabbitmq-server-3.6.10-1.el7.noarch.rpm和erlang-19.0.4-1.el7.cento ...

  9. 13. Forensics (取证 4个)

    Maltego是一个取证和数据挖掘应用程序. 它能够查询各种公共数据源,并以图形方式描绘人员,公司,网站和文档等实体之间的关系. Maltego也是一个开源智能,但不是开源软件. Helix The ...

  10. 链路聚合trunk实现

    用户需求 1,在原有网络基础上实现用户接入Internet 2,监控摄像头不改变原有功能 配置思路 1,首先确定接入交换机是否为管理型交换机 2, 确认接入交换机管理IP 3,划分Vlan  创建tr ...