1.树的概念和结构
树,顾名思义,它看起来像一棵树,是由n个结点组成的非线性的数据结构。
下面就是一颗树:
树的一些基本概念:
结点的度:一个结点含有的子树的个数称为该结点的度; 如上图:A的为6
叶结点或终端结点:度为0的结点称为叶结点; 如上图:B、C、H、I...等结点为叶结点
非终端结点或分支结点:度不为0的结点; 如上图:D、E、F、G...等结点为分支结点
双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点
孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点
兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
树的度:一棵树中,最大的结点的度称为树的度; 如上图:树的度为6
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
树的高度或深度:树中结点的最大层次; 如上图:树的高度为4
堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点
结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
森林:由m(m>0)棵互不相交的树的集合称为森林
2.树的表示
树的表示比线性表复杂,它不仅要存储数据,还要存储和其他结点的关系。
树有很多的表示方法,下面是最为常见的一种:孩子兄弟表示法
typedef int DataType; struct Node { struct Node* firstChild1; // 第一个孩子结点 struct Node* pNextBrother; // 指向其下一个兄弟结点 DataType data; // 结点中的数据域 };
如图:每一个结点都有自己孩子结点和兄弟结点,如果没有就存NULL,这样就可以表示每一个结点了。
3.二叉树的概念和结构
先看下面图:
每一个树干都有两个树枝,这就是我们生活中的二叉树,而数据结构中的二叉树有两种常见又特殊的:
完全二叉树:
满二叉树:
4.二叉树的存储
二叉树的存储有顺序存储和链式存储:
顺序存储:
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树
链式存储:
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链
二叉链:
typedef int BTDataType; // 二叉链 struct BinaryTreeNode { struct BinTreeNode* left; // 指向当前结点左孩子 struct BinTreeNode* right; // 指向当前结点右孩子 BTDataType data; // 当前结点值域 }
三叉链:
// 三叉链 struct BinaryTreeNode { struct BinTreeNode* parent; // 指向当前结点的双亲 struct BinTreeNode* left; // 指向当前结点左孩子 struct BinTreeNode* right; // 指向当前结点右孩子 BTDataType data; // 当前结点值域 };
普通二叉树一般不用顺序结构存储,因为会有空间的浪费,只要完全二叉树才适合顺序存储,也就是堆:
5.堆的概念和结构
堆是一种完全二叉树,堆又分为大堆和小堆。
大堆:每一个父结点都比它的子结点大
小堆:每一个父结点都比子结点小