【数据结构】二叉树
1.什么是二叉树
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分
2.二叉树的结构与特点
1.二叉树大多以链式结构体现,与链表有相似之处,但又不同
2.二叉树的每个节点最多有两课子树,即深度为h的二叉树中至多含有2^h-1个节点
3.二叉树的子树分为左子树与右子树
3.二叉树的类型
满二叉树:一个二叉树,如果每层的节点数都达到最大值(即2),则这个二叉树就是满二叉树
完全二叉树:设一个二叉树的深度为h,其1~h-1层的节点数都到达最大,并且最下层的节点都集中在树的左侧,则该树就是完全二叉树(因此满二叉树是一种特殊的二叉树)
二叉搜索树(B树)与平衡二叉搜索树(AVL树)就不在这里解释,以上仅介绍基础
4.二叉树的实现
本文以链式结构来实现二叉树,实际上还存在另一种顺序结构(以数组实现)的二叉树,但普通的二叉树不适合用该结构来存储
以下是一个普通二叉树节点的定义
struct BTNode
{
BTNode* left_BTNode;//指向当前节点的左孩子
BTNode* right_BTNode;//指向当前节点的右孩子
char data;
};
二叉树的创建(前序遍历方式创建)
BTNode* Create_BinaryTree(vector<char>& str)//返回的根节点表示该二叉树,str为需要转化为二叉树的数组
{
if (str[j] == '#')//用j来指向str
{
return NULL;
}
else
{
BTNode* root = new BTNode;
root->data = str[j];
j++;
root->left_BTNode = Create_BinaryTree(str);
j++;
root->right_BTNode = Create_BinaryTree(str);
return root;//返回根节点
}
}
二叉树的判空
bool IsEmpty(BTNode* root)
{
if (root == NULL)
return true;
else
return false;
}
二叉树的遍历有基础的三种:前序,中序,后序
二叉树的前序遍历(根节点,左节点,右节点)
void PreTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
cout << root->data;
PreTravel(root->left_BTNode);
PreTravel(root->right_BTNode);
return;
}
二叉树的中序遍历(左节点,根节点,右节点)
void MidTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
MidTravel(root->left_BTNode);
cout << root->data;
MidTravel(root->right_BTNode);
return;
}
二叉树的后序遍历(左节点,右节点,根节点)
void BackTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
BackTravel(root->left_BTNode);
BackTravel(root->right_BTNode);
cout << root->data;
return;
}
除此之外还存在一种层序遍历,需要依靠队列(queue)来实现
二叉树的层序遍历(层层遍历)
void LevelTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
queue<BTNode*>que;//定义一个队列
que.push(root);//先将根节点入队
while (!que.empty())//判断队列是否为空
{
int length = que.size();//记录当前队列长度
for (int i = 0; i < length; i++)//遍历当前层
{
auto node = que.front();
if (node->left_BTNode != NULL)
{
que.push(node->left_BTNode);
}
if (node->right_BTNode != NULL)
{
que.push(node->right_BTNode);
}
cout << node->data;
que.pop();
}
}
return;
}
二叉树求最大深度
int MaxDepth(BTNode* root)
{
if (IsEmpty(root))
{
return 0;
}
return max(MaxDepth(root->left_BTNode), MaxDepth(root->right_BTNode)) + 1;//递归求最大深度
}
二叉树的节点查找
BTNode** FindBTNode(BTNode** root, char goal)//这里采取前序遍历查找,同时以二级指针方式传参,是为了后面方便删除节点
{
if (IsEmpty(*root))
{
return NULL;
}
if ((*root)->data == goal)
{
return &(*root);
}
BTNode** ret = FindBTNode(&(*root)->left_BTNode, goal);
if (ret != NULL)
{
return ret;
}
ret = FindBTNode(&(*root)->right_BTNode, goal);
if (ret != NULL)
{
return ret;
}
return NULL;
}
二叉树的节点数据修改
void ModifyBTNode(BTNode* root, char goal, char newdata)
{
BTNode** ret = FindBTNode(&root, goal);//由于find函数采用二级指针传递root,这里要对root再取一次地址
if (ret == NULL)
{
cout << "该节点不存在!";
return;
}
(*ret)->data = newdata;
return;
}
二叉树的节点删除
void DeleteBTNode(BTNode** root, char goal)
{
BTNode** ret = FindBTNode(root, goal);
delete(*ret);
*ret = NULL;//置空该节点
return;
}
二叉树的销毁
void Destroy_BinaryTree(BTNode** root)
{
if (IsEmpty(*root))
{
return;
}
if (!IsEmpty((*root)->left_BTNode))
{
Destroy_BinaryTree(&(*root)->left_BTNode);
}
if (!IsEmpty((*root)->right_BTNode))
{
Destroy_BinaryTree(&(*root)->right_BTNode);
}
delete(*root);
*root = NULL;
return;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
int j = 0;//在外定义一个全局变量j
struct BTNode
{
BTNode* left_BTNode;
BTNode* right_BTNode;
char data;
};
bool IsEmpty(BTNode* root)
{
if (root == NULL)
return true;
else
return false;
}
BTNode* Create_BinaryTree(vector<char>& str)
{
if (str[j] == '#')
{
return NULL;
}
else
{
BTNode* root = new BTNode;
root->data = str[j];
j++;
root->left_BTNode = Create_BinaryTree(str);
j++;
root->right_BTNode = Create_BinaryTree(str);
return root;
}
}
void PreTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
cout << root->data;
PreTravel(root->left_BTNode);
PreTravel(root->right_BTNode);
return;
}
void MidTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
MidTravel(root->left_BTNode);
cout << root->data;
MidTravel(root->right_BTNode);
return;
}
void BackTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
BackTravel(root->left_BTNode);
BackTravel(root->right_BTNode);
cout << root->data;
return;
}
void LevelTravel(BTNode* root)
{
if (IsEmpty(root))
{
return;
}
queue<BTNode*>que;
que.push(root);
while (!que.empty())
{
int length = que.size();
for (int i = 0; i < length; i++)
{
auto node = que.front();
if (node->left_BTNode != NULL)
{
que.push(node->left_BTNode);
}
if (node->right_BTNode != NULL)
{
que.push(node->right_BTNode);
}
cout << node->data;
que.pop();
}
}
return;
}
int MaxDepth(BTNode* root)
{
if (IsEmpty(root))
{
return 0;
}
return max(MaxDepth(root->left_BTNode), MaxDepth(root->right_BTNode)) + 1;
}
BTNode** FindBTNode(BTNode** root, char goal)
{
if (IsEmpty(*root))
{
return NULL;
}
if ((*root)->data == goal)
{
return &(*root);
}
BTNode** ret = FindBTNode(&(*root)->left_BTNode, goal);
if (ret != NULL)
{
return ret;
}
ret = FindBTNode(&(*root)->right_BTNode, goal);
if (ret != NULL)
{
return ret;
}
return NULL;
}
void ModifyBTNode(BTNode* root, char goal, char newdata)
{
BTNode** ret = FindBTNode(&root, goal);
if (ret == NULL)
{
cout << "该节点不存在!";
return;
}
(*ret)->data = newdata;
return;
}
void DeleteBTNode(BTNode** root, char goal)
{
BTNode** ret = FindBTNode(root, goal);
delete(*ret);
*ret = NULL;
return;
}
void Destroy_BinaryTree(BTNode** root)
{
if (IsEmpty(*root))
{
return;
}
if (!IsEmpty((*root)->left_BTNode))
{
Destroy_BinaryTree(&(*root)->left_BTNode);
}
if (!IsEmpty((*root)->right_BTNode))
{
Destroy_BinaryTree(&(*root)->right_BTNode);
}
delete(*root);
*root = NULL;
return;
}
int main()
{
vector<char>str;
for(;;)
{
char s = getchar();
if (s == '\n')
{
break;
}
str.push_back(s);//输入数据
}
BTNode* root = Create_BinaryTree(str);//用root表示二叉树
PreTravel(root);
cout << endl;
MidTravel(root);
cout << endl;
BackTravel(root);
cout << endl;
LevelTravel(root);
cout << endl;
cout << MaxDepth(root)<<endl;
ModifyBTNode(root, 'A', 'H');
PreTravel(root);
cout << endl;
DeleteBTNode(&root, 'B');
Destroy_BinaryTree(&root);
cout << IsEmpty(root);
return 0;
}
输入ABCD##E###FG##HJ###,按前序遍历生成二叉树图:
结果: