出处:PAT A1102
题目:将树进行左右两边反转
思路:后序遍历交换两个节点的值
静态写法(https://blog.csdn.net/xiaohuo0930/article/details/103928980)
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<string>
#include <iostream>
#include<stack>
#include <queue>
using namespace std;
struct node
{
char data;
node* lchild;
node* rchild;
};
node* create()
{
char ch;
node* root;
root = new node;
cin >> ch;
if (ch == '#')
root = NULL;
else
{
root->data = ch;
root->lchild = create();
root->rchild = create();
}
return root;
}
node* preorder(node* root)
{
if (root == NULL)
return root;
cout << root->data;
preorder(root->lchild);
preorder(root->rchild);
}
node* postorder(node* root)
{
if (root == NULL)
return root;
postorder(root->lchild);
postorder(root->rchild);
cout << root->data;
}
node* change(node* root)
{
if (root == NULL)
return root;
swap(root->lchild, root->rchild);
change(root->lchild);
change(root->rchild);
return root;
}
int main()
{
node* root;
root = create();
preorder(root);
cout << endl;
preorder(change(root));
cout << endl;
postorder(change(root));
}
出处:leet101
题目:判断树是否对称
思路:如果左子树的左节点和右子树的右节点相同且左子树的右节点和右子树左节点相同,那么树对称
终止条件:左右节点两边有一方为空返回false,全空返回true
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<string>
#include <iostream>
#include<stack>
#include <queue>
using namespace std;
struct node
{
char data;
node* lchild;
node* rchild;
};
node* create()
{
char ch;
node* root;
root = new node;
cin >> ch;
if (ch == '#')
{
root = NULL;
}
else
{
root->data = ch;
root->lchild = create();
root->rchild = create();
}
return root;
}
void preorder(node *root)
{
if (root == NULL)
{
return;
}
preorder(root->lchild);
preorder(root->rchild);
}
bool check(node* root1, node* root2)
{
//终止条件
if (root1 == NULL && root2 == NULL)return true;
else if (root1 == NULL && root2 != NULL)return false;
else if (root1 != NULL && root2 == NULL)return false;
//单层递归
if (root1->data != root2->data)return false;
bool flag1=check(root1->lchild, root2->rchild);
bool flag2=check(root1->rchild, root2->lchild);
bool isSame = flag1 && flag2;
return isSame;
}
bool isSymmetric(node* root)
{
if (!root)
return true;
else return check(root->lchild,root->rchild);
}
int main()
{
node* root;
root = create();
cout << isSymmetric(root);
}
出处:leet104
题目:得出树的最大深度
树的最大深度等于从根节点到叶子节点的最长路径
思路:后序遍历,递归得到结点左右子树的深度中最大的一边再+1得到根节点的深度。
终止条件:当节点为空时返回0.
int maxDepth(node* root)
{
int depth=0;
if (root == NULL)
return 0;
left=maxDepth(root->left);
right=maxDepth(root->right);
if (left > right)
return left++;
else
return right++;
}
出处:leet105
题目:从前序中序排列构造后序排列
思路:
1.前序中左右,中序遍历左中右。那么前序遍历的第一个节点就是中节点,从中序遍历中找到这个节点k,那么这个节点左边都是左子树节点,右边都是右子树节点。
2.求出左节点的数量记为left
3.对左右子树进行划分:前序左子树:[p_start+1,p_start+left],中序左子树:[in_start,k-1]
前序右子树:[p_start+left+1,p_end],中序左子树:[k+1,in_end]
4.对左右子树递归返回根节点。
出处:PAT
题目:已知后序和中序,求前序排列
思路:
1.后序遍历:左右中,中序遍历:左中右。同上
后序遍历的最后一个节点是中节点,用来划分中序遍历得到左子树节点left
2.后序遍历左子树:[postL,postL+left-1],中序遍历左子树[inL,k-1]
后序遍历右子树:[postL+left,postR-1],中序遍历右子树[k+1,inR]
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<string>
#include <iostream>
#include<stack>
#include <queue>
using namespace std;
int postorder[50] = { 0 };
int inorder[50] = { 0 };
int preorder[50] = { 0 };
struct node
{
int data;
node* lchild;
node* rchild;
};
//前序、中序求后序
node* create(int p_start,int p_end,int in_start,int in_end)
{
//post左右中,inorder左中右,pre中左右
//递归终止条件 如果后序序列长度小于等于0则返回null
//单步逻辑:以先序遍历的根结点作为划分找到中序遍历左边界和右边界
if (p_start > p_end)
return NULL;
node* root = new node;
root->data = preorder[p_start];
//记录中序遍历左子树边界
int k = 0;
for (k = 0; k <= in_end; k++)
{
if (preorder[p_start] == inorder[k])
{
break;
}
}
int left = k - in_start;//左结点数目
root->lchild = create(p_start + 1, p_start + left, in_start, k-1);
root->rchild = create(p_start + left + 1, p_end, k + 1, in_end);
return root;
}
//后序,中序求前序
//node* create(int postL, int postR, int inL,int inR)
//{
// if (postL > postR)
// return NULL;
// node* root = new node;
// root->data = postorder[postR];//后序遍历的最后一个结点是根节点
// int k;//记录根中序遍历节点位置
// for (k = 0; k <= inR; k++)
// {
// if (postorder[postR] == inorder[k])
// {
// break;
// }
// }
// int num_left = k - inL;//左结点个数
// root->lchild = create(postL, postL + num_left - 1, inL, k - 1);
// root->rchild = create(postL + num_left, postR - 1, k + 1, inR);
// return root;
//}
void post_order(node* root)
{
if (root == NULL)
return;
post_order(root->lchild);
post_order(root->rchild);
cout << root->data<<' ';
}
void pre_order(node* root)
{
if (root == NULL)
return;
cout << root->data << ' ';
pre_order(root->lchild);
pre_order(root->rchild);
}
int main()
{
int n;
scanf_s("%d", &n);
for (int i = 0; i < n; i++)
{
scanf_s("%d", &preorder[i]);
}
for (int i = 0; i < n; i++)
{
scanf_s("%d", &inorder[i]);
}
node* l = create(0, n - 1, 0, n - 1);
post_order(l);
}
出处:leet114
题目:将二叉树展开为链表(单侧表示)
思路:对于每个根节点右侧的节点用临时遍历存储左子树,遍历右子树的最右节点将左子树插入到最右节点
//void flatten(node* root)
//{
// node* tmp = root;
// if (root == nullptr)return;
// while (tmp)
// {
// node* p = tmp->right;
// tmp->right = tmp->left;
// tmp->left = nullptr;
// node* t = tmp;
// while (t->right)
// t = t->right;
// t->right = p;
// tmp = tmp->right;
// }
出处:leet222
题目:得到树的总节点个数
思路:层次遍历,得到一个节点计数器就加1
int countNodes(TreeNode* root)
{
queue<TreeNode*>que;
if (root != nullptr)que.push(root);
int res = 0;
while (!que.empty())
{
int size = que.size();
for (int i = 0; i < size; i++)
{
TreeNode* node = que.front();
que.pop();
res++;
if (node->left)que.push(node->left);
if (node->right)que.push(node->right);
}
}
return res;
}