✨✨✨专栏:数据结构
🧑🎓个人主页:SWsunlight
目录
一、基本概念:
1、定义:
编辑
编辑
2、树的成分:
3、树的性质:
二、存储方式:
编辑
双亲表示法:
孩子表示法:
孩子兄弟表示法(左孩子右兄弟):
三、二叉树:
概念:
存储方式:
1、顺序存储(顺序表)
2、链式存储(链表)
一、基本概念:
1、定义:
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。为了使其抽象变得具体、易理解,且 因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的树
如下图:可以将最上面想象成树根,开始发散,然后就分化枝条 👉到最后没有枝条(黑色线)连接的是叶子(叶子节点)
下图就是典型的树结构,树枝是不会有叶子的,所以只有分到最后一步了才是叶子;
注意:你看见过树的枝条会和另一根枝条相交么??正常情况的树不会的;换一个思路:可以理解为这是一个家族族谱,最上面的节点就是老祖,他生了孩子,孩子又继续生孩子,到你这一代即(叶子) 你想一下:家庭关系能乱掉么??要是随便一个祖先都能相交,岂不是伦理问题了!!!乱了,一切都乱了!!!!恐怕这个世界都疯了!!!
图中文字很好理解吧!一个人肯定只有一个爹,当然有个例外——老祖,它的父亲我们找不到,暂且没有
总结:
树是一种非线性的数据结构,它表现的关系是一对多
它是由n(n>=0)个结点组成的有限集,当n = 0时此时只有一个根节点,称为空树。
在任意一棵非空树中应满足:
1.有且仅有一个特殊的根节点,根节点没有前驱结点
2.每一个非根结点有且只有一个父亲结点
除了根结点外,每个子结点可以分为多个不相交的子树,并且子树是不相交的
3.树是递归定义的
4.一颗N个结点的树有N-1条
2、树的成分:
前言:接下里讲述的各种名称是根据选则参考系来说的(例子为开头那张树的图)我们可以选整体一颗树来论,然后在树里面又有许多子树
总结:任何一棵树包含:根和子树——>{根+N棵子树(N>=0)};
- 根节点:类比树根,,没有前驱节点,即没有父亲节点的节点,有且只有一个。所有节点通过直接或间接方式都能找到此根节点。如:A就是这颗树的根节点
- 节点的度:一个节点含有孩子的个数(或者说子树的个数,是我生的孩子(二代),即这个节点有几个孩子)。 如:A的度为3 、B的度为2、E的度为0、J的度为0;
- 叶节点/终端节点:度为0的节,类比树叶 。 如:J、F、K、L、H、I
- 非终端节点/分支节点:度不为0的节点。 如:B、C、D、E、G
- 父亲节点/双亲节点:若一个节点含有子节点。 如:A是B和C、D的父亲
- 子节点/孩子节点:一个节点含有子树的根节点(有父亲)。 如:B是A的孩子(子)节点,若是将B看成一颗子树的根节点 那么 E是B的孩子节点
- 兄弟节点:具有同一个父亲节点(亲兄弟)。 如:E和F是兄弟节点
- 堂兄弟节点:双亲节点在同一成的节点互为堂兄弟。 如:E与G、H、I节点互为堂兄弟
- 节点的祖先:从根节点到该节点所径分支上(唯一路径上)的所有节点(“直系亲属”)如下:红色圈就是一个路径,J的祖先就是E、B、A ; 而A是所有节点的祖
- 子孙:以某个节点为根的子树种,任意一个节点都是该节点(根)的子孙。 如:B的子孙包括E、F、J
- 树的度:一颗树中,最大的 节点的度(生的孩子最多个数 )。 如:上图的树的度为:3
- 路径和路径长度:树中两个结点之间的路径是由这两个结点之间所经过的结点序列构成的,而路径长度是路径上所经过的边的个数(就是连接线的个数)。
- 树的层次:从根开始定义,根结点为第1层,它的子结点为第2层,以此类推
- 树的高度/深度:
- 深度:是从根结点开始自顶向下逐层累加的
- 高度:是从叶结点开始自底向上逐层累加的。
- 树的高度(或深度)是树中结点的最大层数
- 如:上图的高度/深度是 4(与你怎么定义层数有关,第一层你是从0开始,还是从1开始计数,建议从1开始,因为开始时初始位置为0,若是0开始初始位置就是-1了)
- 森林:互不不想交的树(多棵树/多个根节点) 如:并查集
标红的是需要重点记住的
3、树的性质:
- 结点数性质:树中结点的个数 == 所有节点的度数+1(根节点)
- 层数性质:树的高度(层数)等于树中最大的层数,其中每一层包括所有结点中距离根结点最远的结点。
- 度数性质:度为m的树中,第i层的结点数最多为m^(i-1)。 i>=1;
- 结点数量与高度关系:一个高度为h的m叉树最多有 (m^h-1)/(m-1) 个结点。同样,一个具有n个结点的m叉树的最小高度为 logm(n*(m-1)
二、存储方式:
(1)、双亲表示法(2)孩子表示法(3)孩子兄弟表示法
双亲表示法:
我们假设以一组连续空间(数组)存储树的结点,同时在每个结点中,附设一个指示器指示其双亲结点到在表中的位置。也就是说,每个结点除了知道自已是谁以外,还知道它的双亲在哪里。
其中data是数据域,存储结点的数据信息。而parent是指针域,存储该结点的双亲在数组中的下标。
//数组大小
#define MAX_Size 100
typedef int FrDataType;//结点的结构
typedef struct Node
{FrDataType data;int parent;
}Node;
//树的结构
typedef struct Ptree {Node a[MAX_Size];//结点数组int r;//根的位置int n;//节点数}Ptree;
这样的存储结构,我们可以根据结点的parent 指针找到它的双亲结点,所用的时间复杂度为0(1),当到parent为-1时,表示找到了根节点。但是要知道结点的孩子是什么,需要遍历整个结构才行
孩子表示法:
把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则将此单链表设为空。然后n个头指针又组成一个顺序表(线性表),采用顺序存储结构,存放进一个一维数组中,如图所示 数据A的下标为0,然后他的孩子有2个,下标分别为1和2,将1和2,存到了右边的数组中,再为下标1和下标2找孩子结点,下标为1的孩子只有一个,放到数组,以此类推
、
》》》设计两种结点结构,一个是孩子链表的孩子结点。
其中child是数据域,用来存储某个结点在表头数组中的下标。next 是指针域,用来存储指向某结点的下一个孩子结点的指针。
另一个是表头数组的表头结点。
其中data是数据域,存储某结点的数据信息。firstchild 是头指针域存储该结点的孩子链表的头指针。
//树的孩子表示法结构定义
#define MAX_SIZE 100
typedef int FrDataType;
//孩子结点
typedef struct Node {int child;//记录每个孩子下标struct Node* next;
}*ChildPtr;
//表头结点
typedef struct {FrDataType data;ChildPtr firstchild;
}FrBox;
//树结构
typedef struct Ptree{FrBox node[MAX_SIZE];//结点数组int r;//根的位置int n;//和结点数
}Ptree;
孩子兄弟表示法(左孩子右兄弟):
前面考虑了双亲和孩子。现在考虑兄弟来做;对于树这样的层级结构来说,只研究结点的兄弟是不行的,我们观察后发现,任意一棵树, 它的结点的第一个孩子如果存在就是唯一的B,它的右兄弟(“兄弟”是兄弟节点不是堂兄)如果存在也是唯一的;
结构如下:child指向左边的第一个孩子,这么理解:后面我(父亲)陆续的生娃,第二个娃交给老大带,第三的娃交给老二带(A的生的第一个娃就是B,后面又生了娃C,娃C就是娃B的右兄弟,C交给B来带B->C,没有兄弟了就指向NULL)依次类推:
结构如下:
//左孩子右兄弟法 树的定义
typedef int TrDataType;
typedef struct TreeNode
{TrDataType val;//数据struct TreeNode* leftchild;//左孩子struct TreeNode* rightBrother;//右兄弟}TreeNode;
这个其实就是二树,我们用这个方法将其变成了二叉树
三、二叉树:
概念:
定义:二叉树是另一种树形结构,其特点是每个结点至多只有两棵子树( 即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒,所以说是一颗有序树;
与树相似,二叉树也以递归的形式定义。二叉树是n (n≥0) 个结点的有限集合
二叉树的组成均由以下几种情况复合完成
特殊的二叉树:
满二叉树:每一个层的结点数都达到最大值 (满二叉树是一种特殊的完全二叉树)
完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。
二叉排序树:左子树上所有结点的关键字均小于根结点的关键字;右子树上的所有结点的关键字均大于根结点的关键字;左子树和右子树又各是一棵二叉排序树。
平衡二叉树:树上任一结点的左子树和右子树的深度之差不超过1。
斜树:所有的节点都只有左或者右子树
二叉树的性质:
任意一棵树,若结点数量为n,则边的数量为n − 1。
非空二叉树上的叶子结点数等于度为2的结点数加1,即no = n2 + 1 。
非空二叉树上第k层上至多有2k − 1个结点( k ≥ 1 ) 。
高度为h的二叉树至多有2 h− 1个结点( h ≥ 1 ) 。
对完全二叉树按从上到下、从左到右的顺序依次编号1 , 2… ∗ , n 1,2…*,n1,2…∗,n,则有以下关系:
i > 1时,结点i的双亲的编号为i / 2,即当i 为偶数时, 它是双亲的左孩子;当i为奇数时,它是双亲的右孩子。
当2i ≤ n 时,结点i的左孩子编号为2i 否则无左孩子。
当2i + 1 ≤ n 时,结点i的右孩子编号为2i + 1,否则无右孩子。
结点i所在层次(深度)为{ l o g 2 i } +1。
具有n个( n > 0 ) 结点的完全二叉树的高度为{ l o g ~2 n~ } +1。
存储方式:
1、顺序存储(顺序表)
使用数组来实现,一般来说使用数组只适用于完全二叉树;不是完全二叉树会有空间浪费的现象现实中,一般只有堆才会使用数组;在存储结构上是一个数组,逻辑结构上是一个完全二叉树
2、链式存储(链表)
用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子 右孩子在的链结点的存储地址 。链式结构又分为二叉链和三叉链
讲的不是很详细,略微了解一下,具体的等学的更深刻了,继续补充