樹的操作
- 創建樹
- 銷燬樹
- 前序遍歷樹
- 中序遍歷樹
- 後序遍歷樹
- 層次遍歷樹
- 求葉子節點[度爲0]個數
- 求二叉樹第K層節點個數
求二叉樹第K層節點個數
遞歸代碼
// 需要一個數節點
public class TreeNode<T> {
T value;
TreeNode leftChild;
TreeNode rightChild;
public TreeNode() {
}
public TreeNode(T value) {
this.value = value;
}
public void addLeftChild(T value) {
TreeNode child = new TreeNode(value);
this.leftChild = child;
}
public void addRightChild(T value) {
TreeNode child = new TreeNode(value);
this.rightChild = child;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TreeNode<?> treeNode = (TreeNode<?>) o;
return Objects.equals(value, treeNode.value) &&
Objects.equals(leftChild, treeNode.leftChild) &&
Objects.equals(rightChild, treeNode.rightChild);
}
@Override
public int hashCode() {
return Objects.hash(value, leftChild, rightChild);
}
}
import java.util.LinkedList;
import java.util.Queue;
public class TreeTools {
/*
* 前序遍歷遞歸實現
* */
public static <T> void preOrderTravel(TreeNode<T> root) {
if (root == null) {
return;
}
System.out.print(root.value);
System.out.printf("\t");
preOrderTravel(root.leftChild);
preOrderTravel(root.rightChild);
}
/**
* 中序遍歷遞歸實現
*/
public static <T> void midOrderTravel(TreeNode<T> root) {
if (root == null) {
return;
}
midOrderTravel(root.leftChild);
System.out.print(root.value);
System.out.printf("\t");
midOrderTravel(root.rightChild);
}
/**
* 後序遍歷遞歸實現
*/
public static <T> void backOrderTravle(TreeNode<T> root) {
if (root == null) {
return;
}
backOrderTravle(root.leftChild);
backOrderTravle(root.rightChild);
System.out.print(root.value);
System.out.printf("\t");
}
/*
* 層次遍歷:使用隊列
* */
public static <T> void levelTravel(TreeNode<T> root) {
Queue<TreeNode<T>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode<T> node = queue.poll();
if (node.leftChild != null) {
queue.offer(node.leftChild);
}
if (node.rightChild != null) {
queue.offer(node.rightChild);
}
System.out.print(node.value);
System.out.printf("\t");
}
}
/**
* getTreeDepth: 判斷樹的深度
* 樹的深度 = Math.max(從左子樹數到當前節點的深度, 從右子樹數到當前節點的深度)
*
* @param root 根節點
* @return int 返回類型
*/
public static <T> int getTreeDepth(TreeNode<T> root) {
if (root == null) {
return 0;
}
int leftLength = getTreeDepth(root.leftChild) + 1;
int rightDepth = getTreeDepth(root.rightChild) + 1;
return Math.max(leftLength, rightDepth);
}
/**
* getTreeNum: 判斷樹中節點個數
* 思想: 樹節點個數 = 左邊樹節點個數 + 右邊樹節點個數 + 當前樹節點(1)
*
* @param root 根節點
* @return int 返回類型
*/
public static <T> int getTreeNum(TreeNode<T> root) {
if (root == null) {
return 0;
}
return getTreeNum(root.leftChild) + getTreeNum(root.rightChild) + 1;
}
/**
* getNumForKlevel: 求第K層節點個數
* 思路:第K層節點個數 = 第k層左子樹的節點個數 + 第k層右子樹的節點個數
* ps:根節點爲第1層。 樹只有一個根節點
*
* @param root
* @param k
* @return int 返回類型
*/
public static <T> int getNumForKlevel(TreeNode<T> root, int k) {
if (root == null || k < 1) {
return 0;
}
if (k == 1) {
return 1;
}
int leftNum = getNumForKlevel(root.leftChild, k - 1);
int rightNum = getNumForKlevel(root.rightChild, k - 1);
return leftNum + rightNum;
}
/**
* getLeafNum: 求二叉樹中葉子節點的個數
* 葉子節點:沒有左孩子也沒有左孩子
* 思路:二叉樹中葉子節點的個數 = 左葉子節點個數 + 又葉子節點個數
*
* @param root
* @return int 返回類型
*/
public static <T> int getLeafNum(TreeNode<T> root) {
if (root == null) {
return 0;
}
//如果二叉樹左子樹和右子樹皆爲空,說明該二叉樹根節點爲葉子節點,加1.
if (root.leftChild == null && root.rightChild == null){
return 1;
}
return getLeafNum(root.leftChild) + getLeafNum(root.rightChild);
}
/*
* 交換二叉樹每個結點的左孩子和右孩子:
*
* 一路走到左下角,然後交換左下角節點的爲止
* 然後走回頭路
* */
public static<T> TreeNode<T> exchange(TreeNode<T> root){
if (root == null){
return null;
}
TreeNode<T> left = exchange(root.leftChild);
TreeNode<T> right = exchange(root.rightChild);
root.rightChild = left;
root.leftChild = right;
return root;
}
/**
* nodeIsChild: 查看node是否是root的子節點
* 思路:先序遍歷:現在左子樹裏面找,找得到就直接返回,找不到,就在右子樹裏面找
* @param root
* @param node
* @return boolean 返回類型
*/
public static <T> boolean nodeIsChild(TreeNode<T> root, TreeNode<T>node){
if (root == null || node == null){
return false;
}
if (root.equals(node)){
return true;
}
boolean find = nodeIsChild(root.leftChild, node);
if (!find){
find = nodeIsChild(root.rightChild, node);
}
return find;
}
/**
* findAllFatherNode: 返回兩個節點lnode和rnode的以root爲根節點的公共父節點
*
* @param root
* 根節點
* @param lNode
* @param rNode
* @return TreeNode 返回類型
*/
}
public static void main(String[] args) {
TreeNode<Integer> root = new TreeNode<>(1);
root.addLeftChild(2);
root.addRightChild(3);
root.leftChild.addLeftChild(4);
root.leftChild.addRightChild(6);
root.leftChild.rightChild.addLeftChild(5);
System.out.print("前序遍歷:\t");
TreeTools.preOrderTravel(root); //
System.out.print("\n中序遍歷:\t");
TreeTools.midOrderTravel(root);
System.out.print("\n後序遍歷:\t");
TreeTools.backOrderTravle(root);
System.out.print("\n層次遍歷:\t");
TreeTools.levelTravel(root);
System.out.printf("\n遞歸樹的深度:\t%d", TreeTools.getTreeDepth(root));
System.out.printf("\n樹的節點的個數:\t%d", TreeTools.getTreeNum(root));
System.out.printf("\n第3層節點個數\t%d", TreeTools.getNumForKlevel(root, 3));
System.out.printf("\n葉子節點個數:\t%d",TreeTools.getLeafNum(root));
TreeTools.exchange(root);
System.out.print("前序遍歷:\t");
TreeTools.preOrderTravel(root); //
System.out.printf("\nnode是root的子節點?\t%d", TreeTools.nodeIsChild(root, new TreeNode<>(33)) ? 1 : 0);
}
創建隨機二叉樹
public class CreateTree {
// 創建一個隨機二叉樹
public static TreeNode CreateTree(TreeNode root, int value){
if (root == null){
return new TreeNode<>(value);
}
if (Math.random() > 0.5){
if (root.leftChild == null){
root.leftChild = new TreeNode<>(value);
}else{
root = CreateTree(root.leftChild, value);
}
}else{
if (root.rightChild == null){
root.rightChild = new TreeNode<>(value);
}else{
root = CreateTree(root.rightChild, value);
}
}
return root;
}
public static void main(String[] args) {
TreeNode<Integer> root = new TreeNode<>(11);
for (int i = 0; i < 10; i++){
CreateTree(root, i);
}
TreeTools.preOrderTravel(root);
System.out.println();
TreeTools.midOrderTravel(root);
System.out.println();
TreeTools.backOrderTravle(root);
System.out.println(TreeTools.preNodeIsChild(root, new TreeNode<>(19)));
}
}