C语言数据结构基础学习笔记——树
树是一种一对多的逻辑结构,树的子树之间没有关系。
度:结点拥有的子树数量。
树的度:树中所有结点的度的最大值。
结点的深度:从根开始,自顶向下计数。
结点的高度:从叶结点开始,自底向上计数。
树的性质:①树的结点数等于所有结点的度数加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语言数据结构基础学习笔记——树的更多相关文章
- C语言数据结构基础学习笔记——B树
2-3树:是一种多路查找树,包含2结点和3结点两种结点,其所有叶子结点都在同一层次. 2结点:包含一个关键字和两个孩子(或没有孩子),其左孩子的值小于该结点,右孩子的值大于该结点. 3结点:包含两个关 ...
- C语言数据结构基础学习笔记——C语言基础
抽象数据类型(ADT)是指一个数学模型以及定义在该模型上的一组操作,通常用(数据对象,数据关系,基本操作集)这样的三元组来表示抽象数据类型. 数据结构是相互之间存在一种或多种特定关系的数据元素的集合, ...
- C语言数据结构基础学习笔记——动态查找表
动态查找表包括二叉排序树和二叉平衡树. 二叉排序树:也叫二叉搜索树,它或是一颗空树,或是具有以下性质的二叉树: ①若左子树不空,则左子树上所有结点的值均小于它的根结点的值: ②若右子树不空,则右子树上 ...
- C语言数据结构基础学习笔记——图
图(G)由顶点集(V)和边集(E)组成,G=(V,E) 常用概念: ①V(G)表示图G中顶点的有限非空集,V永不为空: ②用|V|表示图G中顶点的个数,也称为图G的阶: ③E(G)表示图G中顶点之间关 ...
- C语言数据结构基础学习笔记——栈和队列
之前我们学过了普通的线性表,接下来我们来了解一下两种特殊的线性表——栈和队列. 栈是只允许在一端进行插入或删除的线性表. 栈的顺序存储结构也叫作顺序栈,对于栈顶指针top,当栈为空栈时,top=-1: ...
- C语言数据结构基础学习笔记——静态查找表
查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找. 查找表:用于查找的数据集合称为查找表,一般有以下操作:①查找是否在表中:②查找属性:③进行操作. 查找表又分为: ①静态查找表:只可以进行 ...
- C语言数据结构基础学习笔记——基础线性表
线性表是指具有相同数据类型的n(n>=0)个数据元素的有限序列,它具有一个表头元素和一个表尾元素,并且每一个数据元素最多只有一个直接前驱和一个直接后继. 线性表的顺序存储也叫作顺序表,它的特性是 ...
- Oracle基础学习笔记
Oracle基础学习笔记 最近找到一份实习工作,有点头疼的是,有阶段性考核,这...,实际想想看,大学期间只学过数据库原理,并没有针对某一数据库管理系统而系统的学习,这正好是一个机会,于是乎用了三天时 ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
随机推荐
- 自动删除Android工程中无用的资源
开发时间久了, 几个版本迭代之后, 工程中难免留下很多垃圾资源, 造成apk的包很大, 这里介绍一个工具, 可以自动扫描工程中, 没有使用的资源, 然后自动删除: 包括图片, xml, 文本等. 采用 ...
- 关于matlab中画图放大局部细节的问题
1)需要用得到一个matnify.m文件,下载地址magnify 2)接下来就是如何使用magnify的问题,参见使用 只是在“使用”中的第二步之前首先要用cd进入magnify所在位置.
- lua中查询表元素规则(__index)解析
阅读文章后用一个流程图来总结__index的规则用法 总结一下Lua查找一个表元素时的规则,其实就是如下3个步骤: 1.在表中查找,如果找到,返回该元素,找不到则继续 2.判断该表是否有元表,如果没有 ...
- APNs
生成推送证书: 1. 登陆开发者中心:https://developer.apple.com2. 点开 certificates.identifiers 和 proversionprofiles 里面 ...
- 用户控件 RadioButtonList
public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, string name, string codeCate ...
- CF300E. Empire Strikes Back
题目链接(是的我越来越懒了..) 题目大意及数据范围: 数据范围很大.“最小”二字让我们考虑二分,但是上界...不会爆long long让你写高精吧? 我们可以发现,∑ai一定满足条件,所以上界是1e ...
- ubuntu typora使用学习
typora使用方法 标题: 对于标题,直接用ctrl+对应数字就是第几级标题 文字格式: ctrl+B/I/U 进入加粗/倾斜/下划模式,不需要符号键入 居中的话 用 CENTER 列表引用: 可直 ...
- 学习笔记CB012: LSTM 简单实现、完整实现、torch、小说训练word2vec lstm机器人
真正掌握一种算法,最实际的方法,完全手写出来. LSTM(Long Short Tem Memory)特殊递归神经网络,神经元保存历史记忆,解决自然语言处理统计方法只能考虑最近n个词语而忽略更久前词语 ...
- [WC2006]水管局长
原题链接 前言 搞不懂为什么要写LCT,搞不懂为什么要加强数据.像这道题是用父亲表示法来做的.虽然复杂度不是log,但是现在下面这份代码却是无论从空间,还是代码量,还是时间都是优秀不止一点. 而且这样 ...
- c# 坑人的发邮件组件
System.Net.Mail 在服务器25端口被封禁的情况下,无法使用其它诸如SSL 465端口发送.用过时的System.Web.Mail却可以.是微软更新速度太快呢,还是标准不一致呢. Syst ...