二叉树
一、树的概念与结构
树是一种非线性的数据结构,它是由n(n>=0)个有限的结点,层往下依次延伸,由于它的逻辑形状,像一颗倒着的树,因此被称为树。
二、树的节点
(1)树有一个特殊的结点叫根节点,根节点无前驱结点。
(2)根节点的额每一个后继结点都可以成为一棵树,称为这棵树的子树,若根结点还有后继结点,那么它的后继结点也称为该数的子树。
(3)子树之间互为独立的树,不可以相交。
(4)除根节点之外,每个结点仅有一个父节点。
(5)一颗n个节点的树有n-1条边,因为根节点无前驱节点。
三、树的相关术语
(1)父结点/双亲结点:若一个结点含有子节点,这个节点称为其子节点的父节点,例:A是B的双亲节点。
(2)子结点/孩子结点:结点的后继结点,称为该结点的孩子结点,例:B、C是A的孩子结点。
(3)结点的度:一个节点孩子的个数就是他的度,例:A的度为2。
(4)叶子结点/终端结点:度为0的结点称为后继结点,例:D、E、F、G。
(5)分支结点/非终端结点:度不为0的结点,例:B、C、A。
(6)树的度:一棵树中最大结点度称为树的度,例:上图中树的度为2。
(7)兄弟节点:具有相同父节点的节点互称为兄弟结点,例:上图中的B、C。
(8)结点的层次:根所在的层为第一层,它的子结点为第二层,以此类推,例:上图中A为第一层,B、C为第二层,D、E、F、G为第三层。
(9)树的高度或深度:树中结点的最大层次,例:上图中树的最大层次为3。
(10)结点的祖先:从根结点所经分支上的所有节点,例:A是所有结点的祖先节点。
(11)路径:从树中的任意一结点出发,沿父节点到子节点,到达任意节点的路线,例:A到E的路径:A、B、E。
(12)子孙:以某结点为根的子树中任意一结点都称为该结点的子孙。
(13)森林:由m(m>0)棵互不相交的集合称为森林。
四、树的表示方法
树的表示方法有很多:双亲表示法、孩子表示法、孩子双亲表示法、以及孩子兄弟表示法。
这里我们采用最常用的孩子兄弟表示法来构建一颗二叉树。
1.孩子兄弟表示法代码结构:
struct TreeNode { int data;//节点中的数据域 struct TreeNode* child;//指向从左边开始第一个孩子结点。 struct TreeNode* brother;//指向右边的下一个兄弟结点。 }
2.孩子兄弟表示法图形
五、二叉树的引入和概念
在树形结构当中我们最长用到的就是二叉树,那么二叉树又是什么呢?二叉树是由m个结点(m>=0)每个结点均有n(0<=n<=2),这样的树我们就称之为二叉树。
注:
(1)二叉树不存在度大于二的结点。
(2)二叉树有左右之分次序不能颠倒,因此二叉树树是有序树。
(3)m为0称为空树。
(4)二叉树由以下几种情况复合而成。
五、特殊的二叉树
1.满二叉树
(1)满二叉树
二叉树的每一层结点都达到最大值,这个树就是满二叉树。
(2)满二叉树的图形
2.完全二叉树
(1)完全二叉树
完全二叉树是由满二叉树所引出出来的,对于深度为k有n个节点的二叉树来说,当且仅当其每一个结点都与深度为k的满二叉树中编号1至n的结点一一对应时称之为完全二叉树,满二叉树是一种特殊的完全二叉树。
(2)完全二叉树的图形
六、二叉树的性质
(1)若规定根结点的层数为1,则一颗非空二叉树的第i层上至多有i的2i-1个结点。
(2)若规定根节点的层数为1,则深度为h的二叉树结点个数是2h-1。
(3)若规定根结点层数为1,具有n个结点则深度h = log(n+1)。
七、二叉树的存储结构
1.顺序结构
一般适用于存储完全二叉树,非完全二叉树的存储会有空间浪费。
2.链式结构存储
对于普通二叉树我们一般采用二叉链来存储,这样可以避免空间的浪费,我们下面的代码都是采用链式的存储结构。
八、二叉树功能的接口
typedef char DataType;
typedef struct TreeNode
{
DataType data;
struct TreeNode* left;
struct TreeNode* right;
}BTNode;
BTNode* BuyNode(char x);
//前序遍历
void PreOrder(BTNode* root);
//中序遍历
void InOrder(BTNode* root);
//后序遍历
void PostOrder(BTNode* root);
//求结点个数
int BinaryTreeSize(BTNode* root);
//求叶子结点的个数
int BinaryTreeLastSize(BTNode* root);
//求第K层结点的个数
int BinaryTreeLeveSize(BTNode* root, int k);
//求二叉树高度
int BinaryTreeDepth(BTNode* root);
//找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, char x);
//二叉树的销毁
void BinaryTreeDestory(BTNode** root);
//层序遍历
void Leve1Order(BTNode* root);
//判断是否为完全二叉树
bool BinaryTreeComplete(BTNode* root);
九、二叉树功能的代码实现
1.先序遍历
//先序遍历
void PreOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
printf("%c ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
2.中序遍历
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
InOrder(root->left);
printf("%c ", root->data);
InOrder(root->right);
}
3.后序遍历
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%c ",root->data);
}
4.求结点个数
//二叉树结点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
5.求叶子结点的个数
//叶子节点的个数
int BinaryTreeLastSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLastSize(root->left) + BinaryTreeLastSize(root->right);
}
6.求第k层结点个数
//求第K层结点的个数
int BinaryTreeLeveSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
//注意--k和k-1
return BinaryTreeLeveSize(root->left, k - 1) + BinaryTreeLeveSize(root->right, k - 1);
}
7.求二叉树的高度
//求二叉树高度
int BinaryTreeDepth(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int leftDepth = BinaryTreeDepth(root->left);
int rightDepth = BinaryTreeDepth(root->right);
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
8.找值为x的结点
//找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, char x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* ListNode = BinaryTreeFind(root->left, x);
if (ListNode)
{
return ListNode;
}
BTNode* RightNode = BinaryTreeFind(root->right, x);
if (RightNode)
{
return RightNode;
}
return NULL;
}
9.二叉树的销毁
//二叉树的销毁
void BinaryTreeDestory(BTNode** root)
{
if (*root == NULL)
{
return;
}
BinaryTreeDestory(&((*root)->left));
BinaryTreeDestory(&((*root)->right));
free(*root);
*root = NULL;
}
10.层序遍历
需要借助栈的结构来实现
//层序遍历
void Leve1Order(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* Top = QueueFront(&q);
printf("%c ", Top->data);
QueuePop(&q);
if (Top->left != NULL)
{
QueuePush(&q, Top->left);
}
if (Top->right != NULL)
{
QueuePush(&q, Top->right);
}
}
QueueDestory(&q);
}
11.判断二叉树是否为完全二叉树
需要借助栈的结构来实现
//判断是否为完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* Top = QueueFront(&q);
QueuePop(&q);
if (Top == NULL)
{
break;
}
QueuePush(&q, Top->left);
QueuePush(&q, Top->right);
}
while (!QueueEmpty(&q))
{
if (QueueFront(&q) != NULL)
{
QueueDestory(&q);
return false;
}
QueuePop(&q);
}
QueueDestory(&q);
return true;
}