本文包括:
1.前序遍历、中序遍历、后序遍历、层序遍历的算法写法
2.根据3种遍历其二,重构二叉树
3.判断二叉树B是不是二叉树A的子结构
4.二叉树的镜像
1、遍历
ps: 二叉树常用的遍历方式有:前序遍历、中序遍历、后序遍历、层序遍历四种遍历方式
(1)前序遍历(根左右)
a、访问根节点;b、前序遍历左子树;c、前序遍历右子树。
(2)中序遍历(左根右)
a、中序遍历左子树;b、访问根节点;c、中序遍历右子树。
(3)后序遍历(左右根)
a、后序遍历左子树;b、后续遍历右子树;c、访问根节点。
二叉树的结构
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
1.1 前序遍历算法
void PreOrder(BTreeNode* BT) {
if(BT != NULL) {
cout << BT->data << ' '; //访问根结点
PreOrder(BT->left); //前序遍历左子树
PreOrder(BT->right); //前序遍历右子树
}
}
1.2 中序遍历算法
void InOrder(BTreeNode* BT) {
if(BT != NULL) {
InOrder(BT->left); //中序遍历左子树
cout << BT->data << ' '; //访问根结点
InOrder(BT->right); //中序遍历右子树
}
}
1.3 后序遍历算法
void PostOrder(BTreeNode* BT) {
if(BT != NULL) {
PostOrder(BT->left); //后序遍历左子树
PostOrder(BT->right); //后序遍历右子树
cout << BT->data << ' '; //访问根结点
}
}
(4)层次遍历
从最顶层的节点开始,从左往右依次遍历,之后转到第二层,继续从左往右遍历,持续循环,直到所有节点都遍历完成
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int>ves;
queue<TreeNode*>q;
TreeNode *front;
q.push(root);
if (root == NULL)return ves;
while (!q.empty()){
front = q.front();
q.pop();
if(front->left){
q.push(front->left);
}
if(front->right){
q.push(front->right);
}
ves.push_back(front->val);
}
return ves;
}
};
层序遍历的思路是,创建一个队列,先将根节点(A)入队,然后用front指针将根节点记下来,再将根节点出队,接下来看front节点(也就是刚才的根节点)有没有左孩子或右孩子,如果有,先左(B)后右(C)入队,最后输出front节点的值,只要队列还不为空,就说明还没有遍历完,就进行下一次循环,这时的队头元素(front)则为刚才入队的左孩子(B),然后front出队,再把它的左右孩子拉进来(如果有),因为队列的先进先出性质,B的左右孩子DE是排在C后面的,然后输出B,下一次循环将会拉人C的左右孩子FG,最后因为FG没有左右孩子,一直出队,没有入队元素,队列迟早会变为空,当队列为空时,整颗树就层序遍历完成了,结束循环。
参考:https://blog.csdn.net/monster_ii/article/details/82115772
2.根据3种遍历其二,重构二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
vector<int>leftchildpre,leftchildvin;
vector<int>rightchildpre,rightchildvin;
int i=0,j;
if(pre.size()==0||pre.size()!=vin.size())return NULL;
if(pre.size()==1)return new TreeNode(pre[0]);
struct TreeNode *head =new TreeNode(pre[0]);
while(vin[i]!=pre[0]){i++;}
for(j=0;j<i;j++){
leftchildvin.push_back(vin[j]);
leftchildpre.push_back(pre[j+1]);
}
for(j=i+1;j<pre.size();j++){
rightchildvin.push_back(vin[j]);
rightchildpre.push_back(pre[j]);
}
head->left=reConstructBinaryTree(leftchildpre,leftchildvin);
head->right=reConstructBinaryTree(rightchildpre,rightchildvin);
return head;
}
};
参考https://www.cnblogs.com/fyzzz9/p/11192791.html里的图片3-1
知道前序遍历,中序遍历,后序遍历中的两个,重构二叉树的方法关键点:找出根节点,由左子树的前序和左子树的中序组成新的前序遍历,中序遍历,找出新的”根节点“;由右子树的前序和右子树的中序组成新的前序遍历和中序遍历,找出新的”根节点“。如此递归
代码注意:要重新struct TreeNode *head =new TreeNode(pre[0]);
递归时:
head->left=reConstructBinaryTree(leftchildpre,leftchildvin);
head->right=reConstructBinaryTree(rightchildpre,rightchildvin);
3.判断二叉树B是不是二叉树A的子结构
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
/*
*1.判断空
2.判断头结点(一个遍历)
3.找到头结点相同后,遍历确认是否相同(一个遍历)
*/
class Solution {
public:
bool HasSubtree(TreeNode* root1, TreeNode* root2)
{
bool result = false;
if(root1!=NULL&&root2!=NULL){
if(root1->val == root2->val){
result = DoesTree1HaveTree2(root1,root2);
}
if(!result)result = HasSubtree(root1->left,root2);
if(!result)result = HasSubtree(root1->right,root2);
}
return result;
}
bool DoesTree1HaveTree2(TreeNode* root1, TreeNode* root2)
{
if(root1 == NULL && root2 != NULL)return false;
if(root2 == NULL)return true;
if(root1->val != root2->val)return false;
return DoesTree1HaveTree2(root1->left,root2->left)&&DoesTree1HaveTree2(root1->right,root2->right);
}
};
关键:1.判断空
2.找出子结构在主树的头结点(遍历)
3.找到的话,遍历看是否是子结构(遍历)
代码:这道题应该学的:
1.找到一棵树对应的点
2.匹配两棵树是否相同
4.二叉树的镜像
题目描述(剑指)
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void Mirror(TreeNode *pRoot) {
if(pRoot){
TreeNode *tmp;
tmp = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = tmp;
//前面4句可以用swap(pRoot>left,pRoot->right);代替
Mirror(pRoot->left);
Mirror(pRoot->right);
}
}
};