算法笔记-第九章-二叉树的遍历
- 二叉树的先序遍历
- 二叉树的中序遍历
- 二叉树的后序遍历
- 二叉树的层次遍历
- 注意点一:
- 注意点二:
- 二叉树的高度
- 二叉树的结点层号
- 翻转二叉树
- 翻转二叉树不同的方法
- 方法一:用栈实现
- 方法二:用队列实现
- 方法三:
二叉树的先序遍历
//二叉树的先序遍历
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 50;
struct Node //用结构体表示左子树和右子树的数据
{
int l, r;
} nodes[MAXN];
vector<int> pre;//设置一个数组用来存储先序遍历的数据
void preOrder(int root)
{
if (root == -1)
{
return;
}
pre.push_back(root);
preOrder(nodes[root].l);//用递归的方式将输入的左子树和右子树都进行重新判断,然后输入到数组当中
preOrder(nodes[root].r);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
preOrder(0);//直接将头结构体带入
//输出数组中数据
for (int i = 0; i < (int)pre.size(); i++)
{
printf("%d", pre[i]);
if (i < (int)pre.size() - 1)
{
printf(" ");
}
}
return 0;
}
二叉树的中序遍历
//思路还是递归的思路
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 50;
struct Node
{
int l, r;
} nodes[MAXN];
vector<int> in;
//思路其实就是利用递归遍历左中右,然后存入到数组当中
void inOrder(int root)
{
if (root == -1)
{
return;
}
inOrder(nodes[root].l);
in.push_back(root);
inOrder(nodes[root].r);
}
//主要是一个函数就是主要的
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
inOrder(0);
for (int i = 0; i < (int)in.size(); i++)
{
printf("%d", in[i]);
if (i < (int)in.size() - 1)
{
printf(" ");
}
}
return 0;
}
二叉树的后序遍历
//这道题目因为还是用递归的方式进行的,所以还是
//简答用递归左右中的方式进行
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 50;
struct Node {
int l, r;
} nodes[MAXN];
vector<int> post;
void postOrder(int root) {
if (root == -1) {
return;
}
postOrder(nodes[root].l);
postOrder(nodes[root].r);
post.push_back(root);
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
postOrder(0);
for (int i = 0; i < (int)post.size(); i++) {
printf("%d", post[i]);
if (i < (int)post.size() - 1) {
printf(" ");
}
}
return 0;
}
二叉树的层次遍历
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int MAXN = 50;
struct Node
{
int l, r;
} nodes[MAXN];
vector<int> layer;
//就是根据遍历的思路来就好
void layerOrder(int root)
{
queue<int> q;
q.push(root);
while (!q.empty())
{
int front = q.front();//去除首元素
q.pop();//删除首元素
layer.push_back(front);
//加入到队列中
if (nodes[front].l != -1)
{
q.push(nodes[front].l);
}
if (nodes[front].r != -1)
{
q.push(nodes[front].r);
}
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
layerOrder(0);
//输入首地址0
for (int i = 0; i < (int)layer.size(); i++
{
printf("%d", layer[i]);
if (i < (int)layer.size() - 1)
{
printf(" ");
}
}
return 0;
}
注意点一:
queue q;和queue<node*> q两者之间的区别是
一个是不可以改变队列中的元素的,一个数带入的时候就是可以直接改变原函数的
注意点二:
层次遍历使用的是队列,基本思路是
访问root,加入队列
如果有左节点,加入左节点
如果有右节点,加入右节点//这里就是要递归方式进行了,
//然后重新进行放问(当然是要用while)
二叉树的高度
//二叉树的高度
//题目本身就是简单的递归遍历
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 50;
struct Node
{
int l, r;
} nodes[MAXN];
int getHeight(int root)
{
if (root == -1)
{
return 0;
}
int leftHeight = getHeight(nodes[root].l);
int rightHeight = getHeight(nodes[root].r);
return max(leftHeight, rightHeight) + 1;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
printf("%d", getHeight(0));
return 0;
}
二叉树的结点层号
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int MAXN = 50;
struct Node
{
int l, r;
} nodes[MAXN];
int layers[MAXN];
void layerOrder(int root)
{
queue<int> q;
q.push(root);
int layer = 1;
while (!q.empty())
{
int cnt = q.size();//一层中有多少个结点
for (int i = 0; i < cnt; i++)
{
int front = q.front();
q.pop();
layers[front] = layer;//结点代表的层数
//
if (nodes[front].l != -1)
{
q.push(nodes[front].l);
}
if (nodes[front].r != -1)
{
q.push(nodes[front].r);
}
}
layer++;//一层一层的来
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
layerOrder(0);
for (int i = 0; i < n; i++)
{
printf("%d", layers[i]);
if (i < n - 1)
{
printf(" ");
}
}
return 0;
}
翻转二叉树
本题就是使用了递归的思路进行翻转二叉树,
再设置两个数组进行遍历二叉树然后输入到数组当中
#include <cstdio>
#include <vector>
#includ e <algorithm>
using namespace std;
const int MAXN = 50;
struct Node
{
int l, r;
} nodes[MAXN];
vector<int> pre, in, post;//
void preOrder(int root)
{
if (root == -1)
{
return;
}
pre.push_back(root);
preOrder(nodes[root].l);
preOrder(nodes[root].r);
}
void inOrder(int root)
{
if (root == -1)
{
return;
}
inOrder(nodes[root].l);
in.push_back(root);
inOrder(nodes[root].r);
}
void revert(int root) //利用的递归将左右孩子节点分别翻转
{
if (root == -1)
{
return;
}
revert(nodes[root].l);
revert(nodes[root].r);
swap(nodes[root].l, nodes[root].r);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &nodes[i].l, &nodes[i].r);
}
revert(0);//用递归的思想进行翻转
preOrder(0);//也都是用递归的思路将二叉树的数据存储到数组当中
inOrder(0);
for (int i = 0; i < (int)pre.size(); i++) //先序遍历
{
printf("%d", pre[i]);
if (i < (int)pre.size() - 1)
{
printf(" ");
}
}
printf("\n");
for (int i = 0; i < (int)in.size(); i++)
{
printf("%d", in[i]);
if (i < (int)in.size() - 1)
{
printf(" ");
}
}
return 0;
}
翻转二叉树不同的方法
方法一:用栈实现
思路:左右节点进行交换,循环翻转每个节点的左右子节点,将未翻转的子节点存入栈中,循环直到栈里所有节点都循环交换完为止
public TreeNode invertTree(TreeNode root)
{
if (root == null)//开始进行判断是否为空
{
return null;
}
Stack<TreeNode> stack = new Stack<>();//设置一个栈
stack.push(root);//将根节点进行入栈
while (!stack.isEmpty())
{
final TreeNode node = stack.pop();//出栈进行访问和翻转孩子结点
final TreeNode left = node.left;
node.left = node.right;
node.right = left;
//下面:从内到外进行翻转,所有先将右变的节点进行入栈,然后进行翻转,然后再是左边的
if (node.left != null)
{
stack.push(node.left);
}
if (node.right != null)
{
stack.push(node.right);
}
}
return root;
}
方法二:用队列实现
/用队列实现
//队列和栈的思路是一样的,都是根据进行入队和出队进行的
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
TreeNode left = node.left;
node.left = node.right;
node.right = left;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return root;
}
方法三:
因为翻转所有的节点的孩子都是翻转左右节点,
所有在递归的思路中=确立了节点,用前序的思路直接遍历和
翻转二叉树,知道节点为NULL
public TreeNode invertTree(TreeNode node) {
if (node == null) {
return null;
}
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
invertTree(node.left);
invertTree(node.right);
return node;
}