目录
1.前序遍历(递归实现)
根>左>右:
优先从根开始遍历,有根则根,无根则左,无左即右,
// 通过构建节点来建立一份二叉树 // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 //第一遍:1 //第二遍:1,2 由于根'1'已经遍历了,我们开始向左走,进行下一轮的"根>左>右" //第三遍:1,2,4由于根'2'已经遍历了,我们继续向左走,进行下一轮的"根>左>右" //第四遍:1,2,4,5 此时,根'4'已经遍历了,而他没有左,我们就返回到4的'父节点'2,注意这个2节点我们已经进行了"根>左"了,我们开始向右遍历的到5 //第五遍:1,2,4,5,3 此时5的左右皆空,返回到2,而2也完成了"根>左>右"继续返回到1,进行1节点的"根>左>右" //第六遍:1,2,4,5,3,6 同上进行3的"根>左>右,得到6 //第七遍:1,2,4,5,3,6,7 在7的左右皆为空后,循环结束
public static void preOrderTraversal1(TreeNode node) {
if (node == null) {
return;
}
System.out.print(node.val + " ");
preOrderTraversal1(node.left);
preOrderTraversal1(node.right);
}
2.中序遍历(递归实现)
"左>根>右"
有左左走,无左回头记本身,换向转右,重复以上
// 中序遍历 // 中序遍历的顺序是左子树-> 根节点-> 右子树。 // 递归写法: // 通过构建节点来建立一份二叉树 // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 //第一遍:4 问"根节点"1,你有左吗?答:有,问"根节点"2,你有左吗?答:有,问"根节点"4,你有左吗?答:无,此时以无左可走,即按照"左>根>右"记录下4 //第二遍:4,2 此时4的左为null,根已经记录,而右亦为空,返回上一级2,2已经进行了"左"现在进行剩下的"根>右"即记录2 //第三遍:4,2,5 同第一遍,由于5没有左,则返回记录本身,同时5的右为空,返回到根节点1, //第四遍:4,2,5,1 节点1的左走完,按照"左>根>右"记录本身1,然后继续向为遍历的">右"遍历 //第五遍:4,2,5,1,6 3节点有左,即先左走,6无左即记录本身,无右,则返回上一级3, //第六遍:4,2,5,1,6,3 懂得都懂,我小3的左都左完了,当然先记录自己本身咯,然后我的右有不为空,当然向右走 //第七遍:4,2,5,1,6,3,7 这个不说大家应该都明白怎么回事,.....算了还是说一下吧 7无左,即记录本身,无右返回,循环结束
public static void inOrderTraversal1(TreeNode node) {
if (node == null) {
return;
}
inOrderTraversal1(node.left);
System.out.print(node.val + " ");
inOrderTraversal1(node.right);
}
3.后序遍历(递归)
"左>根>右" // 通过构建节点来建立一份二叉树 // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 //第一遍:4 有左往左,待到4,无左换右,无右记本身 //第二遍:4,5 退会节点2,走完左边,有右向右,遇无左右的5,即记录 //第三遍:4,5,2 左右走完记本身,同时返回至节点1 //第四遍:4,5,2,6 有右向右,直到6,无左无右,记本身,返回至节点3 //第五遍:4,5,2,6,7 走完左边,有右走右,7无左右记本身,返回至节点3 //第六遍:4,5,2,6,7,3 左右走完记本身,返回至1 //第七遍:4,5,2,6,7,3,1 左右走完,记本身,循环结束
public static void postOrderTraversal1(TreeNode node) {
if (node == null) {
return;
}
postOrderTraversal1(node.left);
postOrderTraversal1(node.right);
System.out.print(node.val + " ");
}
4.层次遍历 (迭代)
树有多高,就遍历几回 // 迭代写法 // 通过构建节点来建立一份二叉树 // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 //第一遍:1 头不为空入队列节点1,根节点1左右不为空,统统录入队列中,此时size长为:2 //第二遍:1,2,3 打印2,入2的左右节点到队列中,打印3,入3的左右节点到队列中,此时size长为:4 //第三遍:1,2,3,4,5,6,7 打印 4,5,6,7,由于他们都没有左右节点,此时size长为:0,循环结束
public static void levelOrderTraversal(TreeNode root){
if(root == null){
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
// System.out.println("size的大小为:"+size);
for(int i = 0; i < size; i++){
TreeNode node = queue.poll();
System.out.print(node.val + " ");
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
}
}
完整代码:
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
this.left = null;
this.right = null;
}
// 前序遍历
// 前序遍历的顺序是根节点 -> 左子树 -> 右子树。
// 递归写法:
// 通过构建节点来建立一份二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
//第一遍:1
//第二遍:1,2 由于根'1'已经遍历了,我们开始向左走,进行下一轮的"根>左>右"
//第三遍:1,2,4由于根'2'已经遍历了,我们继续向左走,进行下一轮的"根>左>右"
//第四遍:1,2,4,5 此时,根'4'已经遍历了,而他没有左,我们就返回到4的'父节点'2,注意这个2节点我们已经进行了"根>左"了,我们开始向右遍历的到5
//第五遍:1,2,4,5,3 此时5的左右皆空,返回到2,而2也完成了"根>左>右"继续返回到1,进行1节点的"根>左>右"
//第六遍:1,2,4,5,3,6 同上进行3的"根>左>右,得到6
//第七遍:1,2,4,5,3,6,7 在7的左右皆为空后,循环结束
public static void preOrderTraversal1(TreeNode node) {
if (node == null) {
return;
}
System.out.print(node.val + " ");
preOrderTraversal1(node.left);
preOrderTraversal1(node.right);
}
// 迭代写法
public static void preOrderTraversal2(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while (node != null || !stack.isEmpty()) {
while (node != null) {
System.out.print(node.val + " ");
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
}
// 中序遍历
// 中序遍历的顺序是左子树-> 根节点-> 右子树。
// 递归写法:
// 通过构建节点来建立一份二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
//第一遍:4 问"根节点"1,你有左吗?答:有,问"根节点"2,你有左吗?答:有,问"根节点"4,你有左吗?答:无,此时以无左可走,即按照"左>根>右"记录下4
//第二遍:4,2 此时4的左为null,根已经记录,而右亦为空,返回上一级2,2已经进行了"左"现在进行剩下的"根>右"即记录2
//第三遍:4,2,5 同第一遍,由于5没有左,则返回记录本身,同时5的右为空,返回到根节点1,
//第四遍:4,2,5,1 节点1的左走完,按照"左>根>右"记录本身1,然后继续向为遍历的">右"遍历
//第五遍:4,2,5,1,6 3节点有左,即先左走,6无左即记录本身,无右,则返回上一级3,
//第六遍:4,2,5,1,6,3 懂得都懂,我小3的左都左完了,当然先记录自己本身咯,然后我的右有不为空,当然向右走
//第七遍:4,2,5,1,6,3,7 这个不说大家应该都明白怎么回事,.....算了还是说一下吧 7无左,即记录本身,无右返回,循环结束
public static void inOrderTraversal1(TreeNode node) {
if (node == null) {
return;
}
inOrderTraversal1(node.left);
System.out.print(node.val + " ");
inOrderTraversal1(node.right);
}
// 迭代写法
public static void inOrderTraversal2(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
System.out.print(node.val + " ");
node = node.right;
}
}
// 后序遍历
// 后序遍历的顺序是左子树 -> 右子树 -> 根节点。
// 递归写法:
// 后序遍历
// 后序遍历的顺序是左子树-> 右子树-> 根节点。
// 递归写法:
// 通过构建节点来建立一份二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
//第一遍:4 有左往左,待到4,无左换右,无右记本身
//第二遍:4,5 退会节点2,走完左边,有右向右,遇无左右的5,即记录
//第三遍:4,5,2 左右走完记本身,同时返回至节点1
//第四遍:4,5,2,6 有右向右,直到6,无左无右,记本身,返回至节点3
//第五遍:4,5,2,6,7 走完左边,有右走右,7无左右记本身,返回至节点3
//第六遍:4,5,2,6,7,3 左右走完记本身,返回至1
//第七遍:4,5,2,6,7,3,1 左右走完,记本身,循环结束
public static void postOrderTraversal1(TreeNode node) {
if (node == null) {
return;
}
postOrderTraversal1(node.left);
postOrderTraversal1(node.right);
System.out.print(node.val + " ");
}
// 迭代写法
public static void postOrderTraversal2(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
//添加一个指向上一个访问的节点的指针,用于判断是否打印父节点
TreeNode prev = null;
TreeNode node = root;
while(node != null || !stack.isEmpty()){
while(node != null){
stack.push(node);
node = node.left;
}
node = stack.peek();
//右子节点为空或者右子节点已经被访问过了,说明当前节点可以被访问了
if(node.right == null || node.right == prev){
System.out.print(node.val + " ");
stack.pop();
prev = node; //更新prev指针,避免重复访问右子节点
node = null;
} else {
node = node.right;
}
}
}
// 层次遍历
// 层次遍历是按层次,从上到下,从左到右遍历每个节点。
// 递归写法:
// 由于层次遍历需要记录当前层次的节点值,故没有递归写法。
//迭代写法:
// 后序遍历
// 后序遍历的顺序是;从头节点开始,至树的高度
// 迭代写法
// 通过构建节点来建立一份二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
//第一遍:1 头不为空入队列节点1,根节点1左右不为空,统统录入队列中,此时size长为:2
//第二遍:1,2,3 打印2,入2的左右节点到队列中,打印3,入3的左右节点到队列中,此时size长为:4
//第三遍:1,2,3,4,5,6,7 打印 4,5,6,7,由于他们都没有左右节点,此时size长为:0,循环结束
public static void levelOrderTraversal(TreeNode root){
if(root == null){
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
// System.out.println("size的大小为:"+size);
for(int i = 0; i < size; i++){
TreeNode node = queue.poll();
System.out.print(node.val + " ");
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
}
}
public static void main(String[] args) {
// 通过构建节点来建立一份二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(7);
System.out.print("前序遍历递归写法: ");
preOrderTraversal1(root);
System.out.println();
System.out.print("前序遍历迭代写法: ");
preOrderTraversal2(root);
System.out.println();
System.out.print("中序遍历递归写法: ");
inOrderTraversal1(root);
System.out.println();
System.out.print("中序遍历迭代写法: ");
inOrderTraversal2(root);
System.out.println();
System.out.print("后序遍历递归写法: ");
postOrderTraversal1(root);
System.out.println();
System.out.print("后序遍历迭代写法: ");
postOrderTraversal2(root);
System.out.println();
System.out.print("层次遍历递归写法: ");
levelOrderTraversal(root);
}
}