在本文中主要对二叉树的常用算法进行分析。主要包括以下几种算法。
- 先序遍历(递归&非递归)
- 中序遍历(递归&非递归)
- 后序遍历(递归&非递归)
- 层序遍历
- 求树高(递归&非递归)
- 求所有祖先节点(后序遍历)
- 求两个节点的最近公共祖先节点(利用后序遍历 & 分治法)
代码都整理在github上。https://github.com/xlrainy123/algorithms-implement-by-java
直接上代码。有些地方写的还有些问题,欢迎指正交流。
package tree;
import utils.Utils;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
public class TreeImpl implements Tree {
private TreeNode root;
public int height;
public TreeImpl(TreeNode root){
this.root = root;
this.height = getHeight(root);
}
/**
* 先序遍历
* @param withRec:可以控制是否采用递归
* @param currentNode
* @return
*/
@Override
public List<TreeNode> preOrder(boolean withRec, TreeNode currentNode){
List<TreeNode> nodeList = new ArrayList<TreeNode>();
if (this == null || this.root == null){
throw new NullPointerException("树为空");
}
preOrder(withRec, currentNode, nodeList);
return nodeList;
}
private void preOrder(boolean withRec, TreeNode currentNode, List<TreeNode> nodeList){
//递归
if ( withRec ){
if (currentNode != null){
nodeList.add(currentNode);
preOrder(withRec, currentNode.left, nodeList);
preOrder(withRec, currentNode.right, nodeList);
}
}else { //非递归
ArrayDeque<TreeNode> stack = new ArrayDeque<TreeNode>();
TreeNode pNode = currentNode;
while(!stack.isEmpty() || pNode != null){
if (pNode != null){
nodeList.add(pNode);
stack.push(pNode);
pNode = pNode.left;
}else {
pNode = stack.pop();
pNode = pNode.right;
}
}
}
}
/**
* 中序遍历
* @param withRec:可以控制是否采用递归
* @param currentNode
* @return
*/
@Override
public List<TreeNode> inOrder(boolean withRec, TreeNode currentNode){
List<TreeNode> nodeList = new ArrayList<>();
if (this.root == null){
throw new NullPointerException("树为空");
}
inOrder(withRec, currentNode, nodeList);
return nodeList;
}
private void inOrder(boolean withRec, TreeNode currentNode, List<TreeNode> nodeList){
if (withRec){
if (currentNode != null){
inOrder(withRec, currentNode.left, nodeList);
nodeList.add(currentNode);
inOrder(withRec, currentNode.right, nodeList);
}
}else {
ArrayDeque<TreeNode> stack = new ArrayDeque<>();
TreeNode pNode = currentNode;
while (! stack.isEmpty() || pNode != null){
if (pNode != null){
stack.push(pNode);
pNode = pNode.left;
}else {
pNode = stack.pop();
nodeList.add(pNode);
pNode = pNode.right;
}
}
}
}
/**
* 后序遍历
* @param withRec:可以控制是否采用递归
* @param currentNode
* @return
*/
@Override
public List<TreeNode> postOrder(boolean withRec, TreeNode currentNode){
List<TreeNode> nodeList = new ArrayList<>();
if (this.root == null){
throw new NullPointerException("树为空");
}
postOrder(withRec, currentNode, nodeList);
return nodeList;
}
private void postOrder(boolean withRec, TreeNode currentNode, List<TreeNode> nodeList){
if (withRec){
System.out.println("递归遍历");
if (currentNode != null){
postOrder(withRec, currentNode.left, nodeList);
postOrder(withRec, currentNode.right, nodeList);
nodeList.add(currentNode);
}
}else {
System.out.println("非递归遍历");
ArrayDeque<TreeNode> stack = new ArrayDeque<>();
TreeNode pNode = currentNode, preVisited = null;
while (!stack.isEmpty() || pNode != null){
if (pNode != null){
stack.push(pNode);
pNode = pNode.left;
}else {
pNode = stack.peekFirst();
if (pNode.right != null && pNode.right != preVisited){
pNode = pNode.right;
stack.push(pNode);
pNode = pNode.left;
}else {
pNode = stack.pop();
nodeList.add(pNode);
preVisited = pNode;
pNode = null;
}
}
}
}
}
/**
* 层序遍历
* @param currentNode
* @return
*/
@Override
public List<TreeNode> levelOrder(TreeNode currentNode){
if (this.root == null){
throw new NullPointerException("树为空");
}
Queue<TreeNode> queue = new ArrayDeque<>();
List<TreeNode> nodeList = new ArrayList<>();
TreeNode pNode = currentNode;
queue.offer(pNode);
while (! queue.isEmpty()){
pNode = queue.poll();
nodeList.add(pNode);
if (pNode.left != null){
queue.offer(pNode.left);
}
if (pNode.right != null){
queue.offer(pNode.right);
}
}
return nodeList;
}
/**
* 求二叉树的高度, 可以有递归和非递归两种求法
* @param currentNode
* @return
*/
@Override
public int getHeight(TreeNode currentNode){
return getHeight(currentNode, false);
}
public int getHeight(TreeNode currentNode, final boolean useLevel){
if (!useLevel){
if (currentNode == null){
return 0;
}
return Math.max(getHeight(currentNode.left, useLevel), getHeight(currentNode.right, useLevel)) + 1;
}else {
int height = 0;
Queue<TreeNode> queue = new ArrayDeque<>();
TreeNode pNode = currentNode;
queue.offer(pNode);
while (! queue.isEmpty()){
int size = queue.size();
for (int i = 0; i < size; i++){
pNode = queue.poll();
if (pNode.left != null){
queue.offer(pNode.left);
}
if (pNode.right != null){
queue.offer(pNode.right);
}
}
height++;
}
return height;
}
}
/**
* 求某个节点的所有祖先节点,利用后续遍历可以得到
* @param child
* @return
*/
@Override
public List<TreeNode> getAllAncestors(TreeNode child){
if (child == root){
return new ArrayList<>(0);
}
ArrayDeque<TreeNode> stack = new ArrayDeque<>();
// List<TreeNode> nodeList = new ArrayList<>();
TreeNode pNode = root;
TreeNode preVisited = null;
while(pNode != null || !stack.isEmpty()){
if (pNode != null){
stack.push(pNode);
pNode = pNode.left;
if (pNode != null && pNode == child){
return new ArrayList<>(stack);
}
}else {
pNode = stack.peekFirst();
if (pNode.right != null && pNode.right != preVisited){
pNode = pNode.right;
if (pNode != null && pNode == child){
return new ArrayList<>(stack);
}
stack.push(pNode);
pNode = pNode.left;
if (pNode != null && pNode == child){
return new ArrayList<>(stack);
}
}else {
pNode = stack.pop();
preVisited = pNode;
pNode = null;
}
}
}
throw new NullPointerException("child节点不存在");
}
/**
* 获取最近公共祖先节点
* @param root
* @param one
* @param two
* @return
*/
public TreeNode getNestestAncestor(TreeNode root, TreeNode one, TreeNode two){
if (root == null || one == root || two == null){
return root;
}
List<TreeNode> nodes1 = getAllAncestors(one);
List<TreeNode> nodes2 = getAllAncestors(two);
if (nodes1.size() < nodes2.size() && nodes2.contains(one)){
return one;
}
if (nodes1.size() > nodes2.size() && nodes1.contains(two)){
return two;
}
int index1 = nodes1.size() - 1, index2 = nodes2.size() - 1;
TreeNode preEqualNode = null;
for ( ; index1 >= 0 && index2 >= 0; ){
if (nodes1.get(index1) == nodes2.get(index2)){
preEqualNode = nodes1.get(index1);
index1 --;
index2 --;
}else {
break;
}
}
return preEqualNode;
}
/**
*
* @param root
* @param one
* @param two
* @param isBetter:选择不同的算法
* @return
*/
public TreeNode getNestestAncestor(TreeNode root, TreeNode one, TreeNode two, final boolean isBetter){
if (!isBetter){
return getNestestAncestor(root, one, two);
}else {
if (root == null || one == root || two == root){
return root;
}
TreeNode left = getNestestAncestor(root.left, one, two, isBetter);
TreeNode right = getNestestAncestor(root.right, one, two, isBetter);
if (left != null && right != null){
return root;
}
System.out.println("better");
return left != null ? left : right;
}
}
@Override
public TreeNode getRoot(){
return this.root;
}
/**
* 更新二叉树的高度属性
* @param currentNode
*/
public void updateHeight(TreeNode currentNode){
this.height = getHeight(currentNode);
}
}