欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java如何創(chuàng)建普通二叉樹(shù)

 更新時(shí)間:2021年07月17日 12:05:35   作者:居十四  
這篇文章主要介紹了java如何創(chuàng)建普通二叉樹(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

java創(chuàng)建二叉樹(shù)

這段時(shí)間一直在復(fù)習(xí)數(shù)據(jù)結(jié)構(gòu)的知識(shí)。

從最基礎(chǔ)的開(kāi)始,實(shí)現(xiàn)一個(gè)普通的二叉樹(shù)。但發(fā)現(xiàn)也不那么簡(jiǎn)單。因?yàn)橹皩W(xué)數(shù)據(jù)結(jié)構(gòu)時(shí)是用C語(yǔ)言寫(xiě)的。

指針用來(lái)對(duì)結(jié)構(gòu)體的值操作比較好理解。但java沒(méi)有指針。

而Node節(jié)點(diǎn)在方法中傳遞的是地址。

如果直接對(duì)形參進(jìn)行new操作是錯(cuò)誤的。無(wú)法改變實(shí)參的值的。這一點(diǎn)坑了我很久,然后一頓查資料。

時(shí)隔很久,終于填上這個(gè)坑了

下面是以遞歸創(chuàng)建的二叉樹(shù).還有一些常見(jiàn)的遍歷和樹(shù)的高度與樹(shù)的最大寬度.

  • 一個(gè)方法不能修改一個(gè)基本數(shù)據(jù)類(lèi)型的參數(shù)
  • 一個(gè)方法可以修改一個(gè)對(duì)象參數(shù)的狀態(tài)
  • 一個(gè)方法不能實(shí)現(xiàn)讓對(duì)象參數(shù)引用一個(gè)新對(duì)象(這句話(huà)在這里尤為適用)

代碼中的二叉樹(shù)如下圖

二叉樹(shù)

下面是非常簡(jiǎn)單的實(shí)現(xiàn)

這里為了,后面的輸出格式,使用了JDK的動(dòng)態(tài)代理。并寫(xiě)了一個(gè)接口

package test.tree; 
public interface AbstractBinaryTree {
 void printPostOder(); 
 void printPostOderByRecursion(); 
 void printPreOder(); 
 void printPreOderByRecursion(); 
 void printInOderByRecursion(); 
 void printInOder(); 
 void printHeight(); 
 void printMaxWidth(); 
 void printLevelOrder();
}

主要的代碼

package test.tree; 
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
 
/**
 * 為了方便展示,并沒(méi)有將Node屬性私有
 */
 
class Node { 
	public String data;
	public Node left = null;
	public Node right = null;
	public boolean flag;
 
	Node(String data) {
		this.data = data;
	}
 
	Node() {
	} 
	@Override
	public String toString() { 
		return this.data;
	} 
}
 
public class BinaryTree implements AbstractBinaryTree{ 
	private Node root = new Node(); 
	public Node getRoot() {
		return root;
	}
 
	public void printNode(Node node) {
 
		if (node.data == null) {
			System.out.print("");
		} else {
			System.out.print(node.data);
		}
	}
 
	public BinaryTree(String tree) {
		String[] treeNodes = tree.split(",");
		createTreeByRecursion(treeNodes);
	}
 
	private int createTreeByRecursion(Node node, String[] treeNodes, int n) { 
		if ("#".equals(treeNodes[n]))
			return n + 1; 
		node.data = treeNodes[n]; 
		node.left = new Node();
		int left = createTreeByRecursion(node.left, treeNodes, n + 1); 
		node.right = new Node();
		int right = createTreeByRecursion(node.right, treeNodes, left); 
		return right;
	}
 
	public void createTreeByRecursion(String[] treeNodes) {
		createTreeByRecursion(root, treeNodes, 0);
	}
 
	/**
	 * 先序非遞歸創(chuàng)建
	 */
	public void createTree(String[] treeNodes) { 
		Stack<Node> stack = new Stack<>(); 
		int index = 0; 
		Node node = root; 
		while (index < treeNodes.length) { 
			while (true) {
 
				if ("#".equals(treeNodes[index])) {
 
					node = stack.pop();
 
					if (node.flag == false) {
						node.left = null;
						node.flag = true;
						stack.push(node);
					} else {
						node.right = null;
					}
 
					// 記得加1
					index++;
					break;
				}
 
				if (node.flag == true) {
					node.right = new Node();
					node = node.right;
				}
 
				node.data = treeNodes[index];
				stack.push(node);
				node.left = new Node();
				node = node.left;
				index++;
			}
 
			if (node.flag == false) {
				stack.push(node);
				node.flag = true;
				node = node.right;
			} else {
				node = stack.peek();
				node.flag = true;
			} 
		} 
	}
 
	// 遞歸調(diào)用的方法,需要將root傳遞進(jìn)去
	private void printPreOderByRecursion(Node node) { 
		if (node == null)
			return; 
		printNode(node);
		printPreOderByRecursion(node.left);
		printPreOderByRecursion(node.right); 
	}
 
	public void printPreOderByRecursion() { 
		printPreOderByRecursion(root);
	}
 
	private void printInOderByRecursion(Node node) {
 
		if (node == null)
			return;
 
		printInOderByRecursion(node.left);
		printNode(node);
		printInOderByRecursion(node.right); 
	}
 
	public void printInOderByRecursion() {
		printInOderByRecursion(root);
	}
 
	private void printPostOderByRecursion(Node node) {
 
		if (node == null)
			return; 
		printPostOderByRecursion(node.left);
		printPostOderByRecursion(node.right);
		printNode(node); 
	}
 
	public void printPostOderByRecursion() { 
		printPostOderByRecursion(root);
	}
 
	// 非遞歸遍歷二叉樹(shù)
 
	// 先序遍歷
	public void printPreOder() { 
		Stack<Node> stack = new Stack<>(); 
		Node tempNode = root; 
		while (true) { 
			while (tempNode != null) {
				printNode(tempNode);
				stack.push(tempNode);
				tempNode = tempNode.left;
			}
 
			if (stack.isEmpty()) {
				break;
			} 
			tempNode = stack.pop();
			tempNode = tempNode.right; 
		} 
	}
 
	// 中序遍歷
	public void printInOder() { 
		Stack<Node> stack = new Stack<>(); 
		Node tempNode = root;
 		while (true) { 
			while (tempNode != null) {
				stack.push(tempNode);
				tempNode = tempNode.left;
			}
 
			if (stack.isEmpty()) {
				break;
			}
			tempNode = stack.pop();
			printNode(tempNode);
			tempNode = tempNode.right; 
		} 
	}
 
	// 后序遍歷
	public void printPostOder() { 
		Stack<Node> stack = new Stack<>(); 
		Node tempNode = root; 
		while (true) {
 
			while (tempNode != null) {
				if (tempNode.flag == true) {
					tempNode = tempNode.right;
				} else {
					stack.push(tempNode);
					tempNode = tempNode.left;
				} 
			}
 
			tempNode = stack.pop(); 
			if (tempNode.flag == false) {
				stack.push(tempNode);
				tempNode.flag = true;
				tempNode = tempNode.right;
			} else {
				printNode(tempNode);
				if (stack.isEmpty()) {
					break;
				}
				tempNode = stack.peek();
				tempNode.flag = true;
			} 
		} 
	}
 
	// 層序遍歷 利用隊(duì)列
	public void printLevelOrder() { 
		Queue<Node> queue = new LinkedList<>(); 
		Node tempNode = root; 
		queue.offer(tempNode); 
		while (!queue.isEmpty()) { 
			Node topNode = queue.poll(); 
			if (topNode == null)
				continue; 
			printNode(topNode);
			queue.offer(topNode.left);
			queue.offer(topNode.right); 
		} 
	}
 
	// 樹(shù)高 遞歸,分別求出左子樹(shù)的深度、右子樹(shù)的深度,兩個(gè)深度的較大值+1
	public int getHeightByRecursion(Node node) { 
		if (node == null) {
			return 0;
		}
		int left = getHeightByRecursion(node.left);
		int right = getHeightByRecursion(node.right);
		return 1 + Math.max(left, right); 
	}
 
	/**
	 * 為什么不直接寫(xiě)成調(diào)用 root,而是另寫(xiě)一個(gè)方法去調(diào)用呢 因?yàn)?這樣可以不再為root,單獨(dú)設(shè)置一個(gè)臨時(shí)變量去存貯
	 * 而且也固定外部調(diào)用的方法,而不用關(guān)心內(nèi)部的實(shí)現(xiàn)
	 */
 
	public void printHeight() { 
		int height = getHeightByRecursion(root); 
		System.out.print(height);
	}
 
	// 利用層序遍歷,得到樹(shù)的最大寬度
	public void printMaxWidth() { 
		Queue<Node> queue = new LinkedList<>();
		Queue<Node> queueTemp = new LinkedList<>();
 
		int maxWidth = 1; 
		Node tempNode = root; 
		queue.offer(tempNode); 
		while (!queue.isEmpty()) { 
			while (!queue.isEmpty()) { 
				Node topNode = queue.poll(); 
				if (topNode == null)
					continue; 
				if (topNode.left.data != null) { 
					queueTemp.offer(topNode.left);
				}
 
				if (topNode.right.data != null) { 
					queueTemp.offer(topNode.right);
				} 
			}
 
			maxWidth = Math.max(maxWidth, queueTemp.size());
			queue = queueTemp;
			queueTemp = new LinkedList<>();
		} 
		System.out.print(maxWidth);
	} 
}

下面是寫(xiě)的測(cè)試類(lèi)

package test.tree; 
import java.lang.reflect.Proxy; 
public class BinaryTreeTest {
 
	public static void main(String[] args) {
		String treeStr = "A,B,D,#,#,#,C,#,E,#,#";
		// String treeStr = "A,#,#";
		AbstractBinaryTree binaryTree =  BinaryTreeTest.proxyBinaryTree(treeStr); 
		binaryTree.printPostOder();
		binaryTree.printPostOderByRecursion();
		binaryTree.printPreOder();
		binaryTree.printPreOderByRecursion();
		binaryTree.printInOderByRecursion();
		binaryTree.printInOder();
		binaryTree.printLevelOrder();
		binaryTree.printHeight();
		binaryTree.printMaxWidth();
	}
 
	public static AbstractBinaryTree proxyBinaryTree(String treeStr) {		
		AbstractBinaryTree binaryTree = new BinaryTree(treeStr); 
		Object newProxyInstance = Proxy.newProxyInstance(binaryTree.getClass().getClassLoader(),
				binaryTree.getClass().getInterfaces(), (proxy, method, args) -> {
					System.out.println(method.getName());
					Object invoke = method.invoke(binaryTree, args);
					System.out.println();
					return invoke;
				});
		
		return (AbstractBinaryTree) newProxyInstance;
	} 
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 生成隨機(jī)單據(jù)號(hào)的實(shí)現(xiàn)示例

    Java 生成隨機(jī)單據(jù)號(hào)的實(shí)現(xiàn)示例

    本文主要介紹了Java 生成隨機(jī)單據(jù)號(hào)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • Java 調(diào)用 HTTP 接口的 7 種方式示例代碼(全網(wǎng)最全指南)

    Java 調(diào)用 HTTP 接口的 7 種方式示例代碼(全網(wǎng)最全指南)

    在開(kāi)發(fā)過(guò)程中,調(diào)用 HTTP 接口是最常見(jiàn)的需求之一,本文將詳細(xì)介紹 Java 中 7 種主流的調(diào)用 HTTP 接口的方式,包括每種工具的優(yōu)缺點(diǎn)和完整代碼實(shí)現(xiàn),感興趣的朋友一起看看吧
    2025-02-02
  • Java使用jni清屏功能的實(shí)現(xiàn)(只針對(duì)cmd)

    Java使用jni清屏功能的實(shí)現(xiàn)(只針對(duì)cmd)

    JNI是Java Native Interface的縮寫(xiě),它提供了若干的API實(shí)現(xiàn)了Java和其他語(yǔ)言的通信(主要是C&C++)。這篇文章主要介紹了Java使用jni清屏功能的實(shí)現(xiàn)(只針對(duì)cmd) ,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05
  • java isPalindrome方法在密碼驗(yàn)證中的應(yīng)用

    java isPalindrome方法在密碼驗(yàn)證中的應(yīng)用

    這篇文章主要為大家介紹了java isPalindrome方法在密碼驗(yàn)證中的簡(jiǎn)單應(yīng)用技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • java ArrayList中的remove方法介紹

    java ArrayList中的remove方法介紹

    大家好,本篇文章主要講的是java ArrayList中的remove方法介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下
    2022-01-01
  • 詳解Java中IO字節(jié)流基本操作(復(fù)制文件)并測(cè)試性能

    詳解Java中IO字節(jié)流基本操作(復(fù)制文件)并測(cè)試性能

    這篇文章主要介紹了Java中IO字節(jié)流基本操作(復(fù)制文件)并測(cè)試性能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 關(guān)于java編譯過(guò)程中的bug說(shuō)明

    關(guān)于java編譯過(guò)程中的bug說(shuō)明

    本篇文章是對(duì)java編譯過(guò)程中的bug進(jìn)行了詳細(xì)的說(shuō)明介紹,需要的朋友參考下
    2013-05-05
  • Java Socket實(shí)現(xiàn)UDP編程淺析

    Java Socket實(shí)現(xiàn)UDP編程淺析

    類(lèi) DatagramSocket 何 DatagramPacket(數(shù)據(jù)包/數(shù)據(jù)報(bào)) 實(shí)現(xiàn)了基于 UDP協(xié)議網(wǎng)絡(luò)程序;UDP數(shù)據(jù)報(bào)通過(guò)數(shù)據(jù)報(bào)套接字 DatagramSocket 發(fā)送和接收,系統(tǒng)不保證 UDP數(shù)據(jù)報(bào)一定能夠安全送達(dá)目的地,也不確定什么時(shí)候可以抵達(dá)
    2022-11-11
  • Springboot詳解如何實(shí)現(xiàn)SQL注入過(guò)濾器過(guò)程

    Springboot詳解如何實(shí)現(xiàn)SQL注入過(guò)濾器過(guò)程

    這篇文章主要介紹了基于springboot實(shí)現(xiàn)SQL注入過(guò)濾器,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2022-06-06
  • Spring針對(duì)AOP詳細(xì)講解

    Spring針對(duì)AOP詳細(xì)講解

    Spring是一個(gè)廣泛應(yīng)用的框架,SpringAOP則是Spring提供的一個(gè)標(biāo)準(zhǔn)易用的aop框架,依托Spring的IOC容器,提供了極強(qiáng)的AOP擴(kuò)展增強(qiáng)能力,對(duì)項(xiàng)目開(kāi)發(fā)提供了極大地便利
    2022-06-06

最新評(píng)論