实现链式结构的二叉树
- 实现链式结构的二叉树
- 遍历
- 前序遍历
- 中序遍历
- 后序遍历
- 节点个数
- 叶子节点个数
- ⼆叉树第k层结点个数
- ⼆叉树的深度/⾼度
- 查找值为X的节点
- 二叉树的销毁
- 层序遍历
- 判断二叉树是否为完全二叉树
⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。 通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址 ,
其结构如下:
typedef int BTDataType; // ⼆叉链
typedef struct BinaryTreeNode
{
struct BinTreeNode* left; // 指向当前结点左孩⼦
struct BinTreeNode* right; // 指向当前结点右孩⼦
BTDataType val; // 当前结点值域
}BTNode;
遍历
前中后序遍历
前序遍历
也叫先根遍历
先遍历根节点,再遍历左子树,最后遍历右子树
左右根
A->B->D->NULL->NULL->NULL->C->E->NULL->NULL->F->NULL->NULL
//前序遍历--根左右
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
中序遍历
先遍遍历左子树,,再遍历根节点,最后遍历右子树
左根右
NULL->D->NULL->B->NULL->A->NULL->E->NULL->C->NULL->F->NULL
//中序遍历--左根右
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%c ", root->data);
InOrder(root->right);
}
后序遍历
先遍历左子树,再遍历右子树,最后遍历根节点
左右根
NULL->NULL->D->NULL->B->NULL->NULL->E->NULL->NULL->F->C->A
//后序遍历--左右根
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%c ", root->data);
}
节点个数
节点个数 = 1(根节点)+ 左子树节点个数 + 右子树节点个数
// ⼆叉树结点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
//节点个数 = 1(根节点)+ 左子树节点个数 + 右子树节点个数
return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
叶子节点个数
叶子节点个数 = 左子树叶子节点个数 + 右子树叶子节点个数
//⼆叉树叶⼦结点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
//叶子节点个数 = 左子树叶子节点个数 + 右子树叶子节点个数
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->left)
+ BinaryTreeLeafSize(root->right);
}
⼆叉树第k层结点个数
当k == 1,直接在当前节点返回,
当k != 1,继续向下一层递归,k-1
//⼆叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1)
+ BinaryTreeLevelKSize(root->right, k - 1);
}
⼆叉树的深度/⾼度
//⼆叉树的深度/⾼度
int BinaryTreeDepth(BTNode* root)
{
if (root == 0)
{
return 0;
}
//高度 = max(左子树,右子树)+ 1
return 1 + max(BinaryTreeDepth(root->left), BinaryTreeDepth(root->right));
}
查找值为X的节点
//⼆叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* leftFind = BinaryTreeFind(root->left, x);
if (leftFind)
{
return leftFind;
}
BTNode* rightFind = BinaryTreeFind(root->right, x);
if (rightFind)
{
return rightFind;
}
return NULL;
}
二叉树的销毁
使用后序遍历
//⼆叉树销毁
void BinaryTreeDestory(BTNode** root)
{
if (*root == NULL)
{
return;
}
BinaryTreeDestory(&((*root)->left));
BinaryTreeDestory(&((*root)->right));
free(*root);
*root = NULL;
}
层序遍历
按照层次依次遍历(从上到下,从左到右)
广度优先遍历
思路:
使用队列,根节点入队,循环判断队列是否为空,不为空取队头,将队头结点左右孩子入队(非空)
//层序遍历
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
//取队头,出队,将左右孩子(非空)入队
BTNode* top = QueueFront(&q);
QueuePop(&q);
printf("%c ", top->data);
if (top->left)
{
QueuePush(&q,top->left);
}
if (top->right)
{
QueuePush(&q, top->right);
}
}
QueueDestory(&q);
}
判断二叉树是否为完全二叉树
// 判断⼆叉树是否是完全⼆叉树
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))
{
BTNode* top = QueueFront(&q);
QueuePop(&q);
if (top != NULL)
{
QueueDestory(&q);
return false;
}
}
QueueDestory(&q);
return true;
}