在前篇文章Java集合框架中我们介绍了排序二叉树、平衡二叉树以及红黑树的概念以及常见的增删操作步骤,这次就学习一下二叉树中常见的一些遍历、翻转等算法,之后刷题时如果遇见相关的题型再做补充。
创建
这里以排序二叉树为例:
public class test {
public static void main(String[] args) {
int[] arr = {5,3,2,0,4,7,1,9,8};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root =node;
}else {
root.add(node);
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
核心思想就是判断当前插入节点的值,与根节点比较,如果小于根节点,就递归插入左子树,如果大于根节点,就递归插入右子树。
遍历
首先看深度优先遍历的前/中/后序遍历(递归和非递归)以及层序遍历方法:
先序遍历: 根->左->右
中序遍历: 左->根->右
后序遍历: 左->右->根
public class test {
public static void main(String[] args) {
int[] arr = {5,3,2,0,4,7,1,9,8};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.preTraverse();
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root =node;
}else {
root.add(node);
}
}
public void preTraverse() {
if(root !=null) {
root.preTraverse();
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
public void preTraverse() {
//System.out.print(this.value+" ");//前序
if(this.leftNode!=null) {
this.leftNode.preTraverse();
}
System.out.print(this.value+" ");//中序
if(this.rightNode!=null) {
this.rightNode.preTraverse();
}
//System.out.print(this.value+" ");//后序
}
}
这里以中序为例,先访问左子树,再根,再右子树,那么输出的序列应为有序序列,运行结果如下:
非递归方法:
//先序遍历
public static void preOrder2() {
if(root == null) return;
Stack<Node> q = new Stack<Node>();
q.add(root);
while(!q.isEmpty()){
Node temp = q.pop();
System.out.print(temp.value +" ");
if(temp.rightNode!=null) q.add(temp.rightNode);
if(temp.leftNode!=null) q.add(temp.leftNode);
}
}
//中序遍历
public void midTraverse() {
if(root == null) return;
Stack<Node> stack = new Stack<>();
while(root!=null || !stack.isEmpty()) {
while (root!=null) {
stack.push(root);
root = root.leftNode;
}
if(!stack.isEmpty()) {
root = stack.pop();
System.out.print(root.value+" ");
root = root.rightNode;
}
}
}
//后序遍历
public void posTraverse() {
List<Integer> list = new ArrayList<>();
if(root == null) return;
Stack<Node> q = new Stack<Node>();
q.add(root);
while(!q.isEmpty()){
Node temp = q.pop();
list.add(temp.value);
if(temp.leftNode!=null) q.add(temp.leftNode);
if(temp.rightNode!=null) q.add(temp.rightNode);
}
for(int i=list.size()-1;i>=0;i--) {
System.out.print(list.get(i)+" ");
}
}
接着看层序遍历(BFS广度优先):
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int[] arr = {5,3,2,0,4,7,1,9,8};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.traver_bfs();
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
public void traver_bfs() {
if(root!=null) {
bfs(root);
}
}
public void bfs(Node root) {
if (root == null)
return;
LinkedList<Node> list = new LinkedList<Node>();
list.add(root);
Node currentNode;
while(!list.isEmpty()) {
currentNode = list.poll();
System.out.print(currentNode.value+" ");
if(currentNode.leftNode!=null){
list.add(currentNode.leftNode);
}
if(currentNode.rightNode!=null) {
list.add(currentNode.rightNode);
}
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
运行结果如下:
左右翻转
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int[] arr = {5,3,2,0,4,7,1,9,8};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.invert_tree();
binarySortTree.traver_bfs();
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
public void invert_tree() {
invert(root);
}
public void invert(Node root) {
if(root == null) return;
Node temp = root.leftNode;
root.leftNode = root.rightNode;
root.rightNode = temp;
invert(root.leftNode);
invert(root.rightNode);
}
public void traver_bfs() {
if(root!=null) {
bfs(root);
}
}
public void bfs(Node root) {
if (root == null)
return;
LinkedList<Node> list = new LinkedList<Node>();
list.add(root);
Node currentNode;
while(!list.isEmpty()) {
currentNode = list.poll();
System.out.print(currentNode.value+" ");
if(currentNode.leftNode!=null){
list.add(currentNode.leftNode);
}
if(currentNode.rightNode!=null) {
list.add(currentNode.rightNode);
}
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
运行结果如下:
查找最大值
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int[] arr = {7,3,10,12,5,1,9,8,7};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.q_maxValue1();
binarySortTree.q_maxValue2();
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
public void q_maxValue1() {
int maxValue = maxValue1(root);
//System.out.println(maxValue);
}
public int maxValue1(Node root) {
if (root == null) return 0;
int right = maxValue1(root.rightNode);
return Math.max(root.value, right);
}
public void q_maxValue2() {
int maxValue = maxValue2(root);
System.out.println(maxValue);
}
public int maxValue2(Node root) {
if (root == null) {
return Integer.MIN_VALUE;
}else {
int left = maxValue2(root.leftNode);
int right = maxValue2(root.rightNode);
return Math.max(Math.max(left, right), root.value);
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
运行结果如下:
最大深度
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int[] arr = {7,3,10,12,5,1,9,8,7};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.q_maxDepth();
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
public void q_maxDepth() {
int maxdepth = maxDepth(root);
System.out.println(maxdepth);
}
public int maxDepth(Node root) {
if (root == null) return 0;
int left = maxDepth(root.leftNode);
int right = maxDepth(root.rightNode);
return Math.max(left, right) + 1;
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
运行结果:
最小深度
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int[] arr = {7,3,10,12,5,1,9,8,7};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.q_minDepth();
}
}
class BinarySortTree{
private Node root;
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
public void q_minDepth() {
int mindepth = minDepth(root);
System.out.println(mindepth);
}
public int minDepth(Node root) {
if (root == null) return 0;
int left = minDepth(root.leftNode);
int right = minDepth(root.rightNode);
if (left == 0) {
return right + 1;
} else if (right == 0) {
return left + 1;
} else {
return Math.min(left, right) + 1;
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
运行结果:
平衡二叉树判断
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int[] arr = {50,25,75,37};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.judgeBalance();
}
}
class BinarySortTree{
private Node root;
Boolean isBalance = true;
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
public void judgeBalance() {
judgeTree(root);
System.out.print(isBalance);
}
public int judgeTree(Node node) {
if(node == null || isBalance == false) {
return 0;
}
int judgeLeft = judgeTree(node.leftNode);
int judgeRight = judgeTree(node.rightNode);
if(Math.abs(judgeLeft - judgeRight) > 1) {
isBalance = false;
}
return Math.max(judgeLeft, judgeRight)+1;
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
排序二叉树判断
这里采用中序遍历,如果前节点不小于当前节点的值,则不符合排序二叉树的条件:
public class test {
public static void main(String[] args) {
int[] arr = {5,3,2,0,4,7,1,9,8};
BinarySortTree binarySortTree = new BinarySortTree();
for(int i=0;i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
binarySortTree.midTraverse();
}
}
class BinarySortTree{
private Node root;
Boolean isBinarySortTree = true;
Node preNode = null;
public void add(Node node) {
if(root == null) {
root =node;
}else {
root.add(node);
}
}
public void midTraverse() {
midTraverse(root);
System.out.print(isBinarySortTree);
}
public void midTraverse(Node root) {
if (root != null) {
midTraverse(root.leftNode);
if(preNode != null && preNode.value>=root.value) isBinarySortTree = false;
preNode = root;
midTraverse(root.rightNode);
}
}
}
class Node{
int value;
Node leftNode;
Node rightNode;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.leftNode == null) {
this.leftNode = node;
}else {
this.leftNode.add(node);
}
}else {
if(this.rightNode == null) {
this.rightNode = node;
}else {
this.rightNode.add(node);
}
}
}
}
这里由于建树的时候就是建立的排序二叉树,因此输出为true:
排序二叉树中第K小的元素
这里其实也可以用中序遍历的方法,为什么中序遍历最后事有序的呢?可以参考上图,如果将每个节点的值投影到坐标轴上,最终得到的就是一个有序序列,而中序遍历的遍历顺序和这种投影所形成的顺序是相通的。