1.树
-
概念:树是一种非线性的数据结构,它是由n个有限结点组成一个具有层次关系的集合。
-
特点:每个结点有零个或多个子结点;没有父结点的结点称为根结点;每一个非根结点有且只有一个父结点;除了根结点外,每个子结点可以分为多个不相交的子树。
-
树的结构如下图所示:
-
节点的度:一个节点含有的子树的个数称为该节点的度。上图节点A的度为4。
-
叶子节点:度为0的节点称为叶子节点。上图叶子节点为B、F、G、H、E。
-
分支节点:度不为0的节点称为分支节点。上图分支节点为C、D。
-
父结点:若一个节点含有子节点,则这个节点是它子结点的父结点。上图节点C是节点F和节点G的父结点,节点D是节点H的父结点。
-
子结点:一个节点含有的子树的根结点称为该节点的子结点。上图节点F、节点G是节点C的子结点,节点H是节点D的子结点,节点B、C、D、E是节点A的子结点。
-
兄弟节点:具有同一个父节点的节点之间称为兄弟节点。上图节点F和节点G称为兄弟节点,节点B、节点C、节点D和节点E称为兄弟节点。
-
节点的祖先:从根节点到该节点所经的分支上的所有节点都称为该节点的祖先。
-
子孙节点:以某节点为根节点的子树上的任一节点都称为该根节点的子孙节点。上图若以节点A为根节点,节点B、节点C、节点D、节点E、节点F、节点G和节点H都是节点A的子孙节点。若以节点C为根节点,则节点F和节点G为节点C的子孙节点。
-
树的度:一棵树中,最大的节点的度称为树的度。上图树的度是3。
-
节点的层次:从根节点起开始定义,根节点为第一层,根节点的子节点为第二层,根节点的子节点的子节点为第三层…依次类推。上图节点A为第一层,节点B、节点C、节点D和节点E为第二层,节点F、节点G和节点H为第三层。
-
树的深度:树中最大的层次称为树的深度,或称为树的高度。上图树的深度或树的高度为3。
-
堂兄弟节点:父节点在同一层次的节点称为堂兄弟节点。上图节点F、节点G和节点H是堂兄弟节点。
-
森林:由n(n>0)棵互不相交的树的集合称为森林。
(1.)树的表示(左孩子右兄弟法)
- 示意图:
// 左孩子右兄弟法
typedef int DataType;
struct Node
{
struct Node* _firstChild;// 第一个子节点
struct Node* _pNextBrother;// 兄弟节点,指向其下一个兄弟节点
DataType _data;
};
2.二叉树
- 概念:一棵二叉树是节点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵树别称为左子树和右子树的二叉树组成。
- 特点:① 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。 ② 二叉树的子树有左右之分,其子树的次序不能颠倒。
- 满二叉树:若一个二叉树除了叶子节点之外,所有节点的度为2的二叉树称为满二叉树。即一个二叉树的层数如果是k,且结点总数是(2 * k) - 1,则它就是满二叉树。
- 完全二叉树:完全二叉树是由满二叉树而引出来的。若一棵二叉树,除了最后一层节点,是一棵满二叉树,并且最后一层的节点是从左到右依次排列,则称该二叉树是完全二叉树。
- 满二叉树是特殊的完全二叉树。满二叉树和完全二叉树的示意图如下:
(1.)顺序存储 - 顺序结构存储就是使用数组来存储,一般使用数组只适合完全二叉树,因为不是完全二叉树会有空间的浪费。二叉树顺序存储在物理上是一个数组,在逻辑上是一棵二叉树。
(2.)链式存储
- 二叉树的链式存储结构是用链表来表示一棵二叉树,即用链式来指示元素的逻辑关系。通常的方法是链表中每个节点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。
- 链式结构分为二叉链和三叉链
// 二叉链
typedef int BTDataType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;// 指向当前结点的左孩子
struct BinaryTreeNode* _pRight;// 指向当前结点的右孩子
BTDataType _data;// 当前结点的数值
}BinaryTreeNode;
(3.)二叉树的构建(先序遍历构建)
// 用先序遍历构建二叉树
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;
struct BinaryTreeNode* _pRight;
char _data;
}BinaryTreeNode;
BinaryTreeNode* createTree(char* str, int* pi)
{
if(str[*pi] == '#')
return NULL;
BinaryTreeNode* node = (BinaryTreeNode*)malloc(sizeof(BianryTreeNode));
node->_data = str[*pi];
++(*pi);
node->_pLeft = createTree(str, pi);
++(*pi);
node->_pRight = createTree(str, pi);
return node;
}
(4.)二叉树的前序遍历
//二叉树的前序遍历
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;
struct BinaryTreeNode* _pRight;
char _data;
}BinaryTreeNode;
void _prevOrderTraversal(BinaryTreeNode* root)
{
if(root == NULL)
return ;
printf("%c ", root->_data);
_prevOrderTraversal(root->_pLeft);
_prevOrderTraversal(root->_pRight);
}
(5.)二叉树的中序遍历
// 二叉树的中序遍历
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;
struct BinaryTreeNode* _pRight;
char _data;
}BinaryTreeNode;
void _InOrderTraversal(BinaryTreeNode* root)
{
if(root == NULL)
return ;
_InOrderTraversal(root->_pLeft);
printf("%c ", root->_data);
_InOrderTraversal(root->_pRight);
}
(6.)二叉树的后序遍历
// 二叉树的后序遍历
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;
struct BinaryTreeNode* _pRight;
char _data;
}BinaryTreeNode;
void _posOrderTraversal(BinaryTreeNode* root)
{
if(root == NULL)
return ;
_posOrderTraversal(root->_pLeft);
_posOrderTraversal(root->_pRight);
printf("%c ", root->_data);
}
(7.)二叉树的层序遍历
// 二叉树的层序遍历
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;
struct BinaryTreeNode* _pRight;
char _data;
}BinaryTreeNode;
void BinaryTreeNodeLevelOrder(BinaryTreeNode* root)
{
Queue q;
QueueInit(&q);
if(root == NULL)
QueuePush(&q, root);
while(!QueueEmpty(&q))
{
BinaryTreeNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->_data);
if(front->_pLeft)
QueuePush(&q, front->_pLeft);
if(front->_pRight)
QueuePush(&q, front->_pRight);
}
printf("\n");
}