二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 。
文章目录
- 前言
- 一、前置说明
-
二、二叉树的遍历
- 1.二叉树的手动创建
- 2.前序、中序以及后续的遍历
- 三、节点的个数以及高度等
- 四、关于二叉树的题目
- 五、层序遍历
前言
由于二叉树的链式结构的一些增删查改没有什么意义,但为什么需要学习呢?
1、主要是为了学习后面二叉树更复杂的数据结构铺垫(红黑树、AVL树、搜索二叉树、B树(多叉平衡搜索树)……)。
2、由于大部分的题目中普通二叉树涉及较多。
一、前置说明
在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。此处手动快速创建一棵简单的二叉树,快速进入二叉树
操作学习,等二叉树结构了解的差不多时,反过头再来研究二叉树真正的创建方式。
二、二叉树的遍历
1.二叉树的手动创建
代码如下(示例):
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
BinaryTreeNode* left;
BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{
BTNode* node = new BTNode;
assert(node);
node->data=x;
node->left = nullptr;
node->right = nullptr;
return node;
}
BTNode* CreatBinaryTree()
{
BTNode* node1 = BuyNode(1);
BTNode* node2 = BuyNode(2);
BTNode* node3 = BuyNode(3);
BTNode* node4 = BuyNode(4);
BTNode* node5 = BuyNode(5);
BTNode* node6 = BuyNode(6);
node1->left = node2;
node1->right = node4;
node4->left = node5;
node4->right = node6;
node2->left = node3;
return node1;
}
2.前序、中序以及后续的遍历
1.前序遍历
(Preorder Traversal
亦称先序遍历
)——
访问根结点的操作发生在遍历其左右子树之前
图示:
void PreOrder(BTNode* root)
{
if (root == nullptr)
return;
cout << root->data<<" ";
PreOrder(root->left);
PreOrder(root->right);
}
void Inorder(BTNode* root)
{
if (root == nullptr)
return;
Inorder(root->left);
cout << root->data << " ";
Inorder(root->right);
}
3. 后序遍历(postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
void postorder(BTNode* root)
{
if (root == nullptr)
return;
postorder(root->left);
postorder(root->right);
cout << root->data << " ";
}
3.节点的个数以及高度等
1.求节点的数量
int BinaryTreeSize(BTNode* root)
{
if (root == nullptr)
return 0;
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
2.求叶子节点的数量
int BinaryLeafSize(BTNode* root)
{
if (root == nullptr)
return 0;
if (root->left == nullptr && root->right == nullptr)
return 1;
return BinaryLeafSize(root->left) + BinaryLeafSize(root->right);
}
3.求第K层的节点数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
assert(k >= 1);
if (root == nullptr)
return 0;
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->left,k-1) + BinaryTreeLevelKSize(root->right,k-1);
}
4.查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == nullptr)
return nullptr;
if (root->data == x)
return root;
BTNode* ret1 = BinaryTreeFind(root->left, x);
if (ret1)
return ret1;
BTNode* ret2 = BinaryTreeFind(root->left, x);
if (ret2)
return ret2;
return nullptr;
}
5、求树的高度
int BinaryTreeDepth(BTNode*root)
{
if (root == nullptr)
return 0;
int LeftDepth = BinaryTreeDepth(root->left) ;
int RightDepth = BinaryTreeDepth(root->right) ;
return LeftDepth > RightDepth ? LeftDepth+1 : RightDepth+1;
}
6、二叉树的销毁
void BinaryTreeDestroy(BTNode* root)
{
if (root == nullptr)
return;
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
delete root;
}
7、判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
queue<BTNode*>q;
if (root)
q.push(root);
while (!q.empty())
{
BTNode* front = q.front();
q.pop();
if (front)
{
q.push(front->left);
q.push(front->right);
}
else
{ //遇到空以后跳出循环
break;
}
//如果后面全是空则是完全二叉树
//如果空后面还有非空不是完全二叉树
while (!q.empty())
{
BTNode* front = q.front();
q.pop();
if (front)
{
return false;
}
}
return true;
}
}
四、关于二叉树的题目
1.单值二叉树。Oj链接
第一种方法:
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool PreOrder(TreeNode*root,int BasicValue)//前序遍历
{
if(root==nullptr)
return true;
if(root->val!=BasicValue)
return false;
return PreOrder(root->left,BasicValue)&&PreOrder(root->right,BasicValue);
}
bool isUnivalTree(TreeNode* root) {
if(root==nullptr)
return true;
return PreOrder(root,root->val);
}
};
第二种方法:
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isUnivalTree(TreeNode* root) {
if(root==nullptr)
return true;
if(root->left&&root->left->val!=root->val)
{
return false;
}
if(root->right&&root->right->val!=root->val)
{
return false;
}
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}
};
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==nullptr)
return 0;
int LeftDepth=maxDepth(root->left);
int RightDepth=maxDepth(root->right);
return LeftDepth>RightDepth?LeftDepth+1:RightDepth+1;
}
};
3.检查两颗树是否相同。OJ链接
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p==nullptr&&q==nullptr)//p,q两树都为空
return true;
if(p==nullptr||q==nullptr)//p,q两树其中一个为空
return false;
if(p->val!=q->val)//p,q两树都不为空
return false;
return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}
};
4.对称二叉树。OJ链接
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSymmetricCompare(TreeNode*root1,TreeNode*root2)
{
if(root1==nullptr&&root2==nullptr)//根节点都为空
return true;
if(root1==nullptr||root2==nullptr)//根节点不都为空
return false;
if(root1->val!=root2->val)//左子树的val不等于右子树的val继续
return false;
return isSymmetricCompare(root1->left,root2->right)&&isSymmetricCompare(root1->right,root2->left);//左子树的左孩子等于右子树的右孩子,左子树的右孩子等于右子树的左孩子
}
bool isSymmetric(TreeNode* root) {
if(root==nullptr)
return true;
return isSymmetricCompare(root->left,root->right);
}
};
5.二叉树的前序遍历。 OJ链接
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void PreOrder(TreeNode*root,vector<int>&v)
{
if(root==nullptr)//前序遍历先访问根节点若为空直接返回
return;
v.push_back(root->val);//若不为空尾插到容器中
PreOrder(root->left,v);//再遍历左子树和右子树
PreOrder(root->right,v);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int>v;
PreOrder(root,v);
return v;
}
};
6.二叉树中序遍历 。OJ链接
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void Inorder(TreeNode*root,vector<int>&v)
{
if(root==nullptr)
return;
Inorder(root->left,v);//中序遍历先访问左子树再遍历根
v.push_back(root->val);//若不为空尾插到容器中
Inorder(root->right,v);//最后再遍历右子树
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>v;
Inorder(root,v);
return v;
}
};
7.二叉树的后序遍历 。OJ链接
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void postorder(TreeNode*root,vector<int>&v)
{
if(root==nullptr)
return;
postorder(root->left,v);//后序序遍历先访问左子树若为空直接返回
postorder(root->right,v);//再遍历右子树和根
v.push_back(root->val);//若不为空尾插到容器中
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int>v;
postorder(root,v);
return v;
}
};
8.另一颗树的子树。OJ链接
/**
* DeFinition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p==nullptr&&q==nullptr)//p,q两树都为空
return true;
if(p==nullptr||q==nullptr)//p,q两树其中一个为空
return false;
if(p->val!=q->val)//p,q两树都不为空
return false;
return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}
bool isSubtree(TreeNode* root, TreeNode* subroot) {
if(root==nullptr)//若为空即不符合
return false;
if(isSameTree(root,subroot))//遍历与当前树进行比较
return true;
return isSubtree(root->left,subroot)||isSubtree(root->right,subroot);
}
};
9.二叉树的构建及遍历。OJ链接
#include<iostream>
using namespace std;
class BinaryTreeNode
{
public:
BinaryTreeNode(char ch='0')
:val(ch)
,left(nullptr)
,right(nullptr)
{
}
BinaryTreeNode* BuyTreeNode(char ch)
{
BinaryTreeNode* node = new BinaryTreeNode(ch);
return node;
}
BinaryTreeNode* CreateTree(string str, int& pi)
{
if (str[pi] == '#')
{
pi++;
return nullptr;
}
BinaryTreeNode* root = BuyTreeNode(str[pi++]);
root->left = CreateTree(str, pi);
root->right = CreateTree(str, pi);
return root;
}
void Inorder(BinaryTreeNode* root)
{
if (root == nullptr)
return;
Inorder(root->left);
cout << root->val<<" ";
Inorder(root->right);
}
private:
char val;
BinaryTreeNode* left;
BinaryTreeNode* right;
};
int main()
{
string str1;
int i = 0;
cin >> str1;
BinaryTreeNode tree;
BinaryTreeNode* root = tree.CreateTree(str1, i);
tree.Inorder(root);
}
五.层序遍历
除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在
层数为
1
,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第
2
层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
void LevelOrder(BTNode* root)
{
queue<BTNode*>q;
if (root)
q.push(root);
while (!q.empty())
{
auto front = q.front();
cout << front->data;
q.pop();
if (front->left)
q.push(root->left);
if (front->right)
q.push(root->right);
}
}
原文地址:https://www.jb51.cc/wenti/3287073.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。