java树算法_Java数据结构算法(三)树
本文旨作于收集整理使用!!
導航
一、樹
樹(Tree)是n(n≥0)個結點的有限集,n=0稱之為空樹。在非空樹種:當有且僅有一個特定的稱為根(Root)的結點; 其余結點可以劃分為m(m>0)個互不相交的有限集T1、T2 、…、Tm,每個集Ti(1≤i≤m)均為樹,且稱為樹的子樹(SubTree), 如下圖所示。
根節(jié)點:根節(jié)點指沒有雙親結點的結點,一棵樹中最多有一個根節(jié)點(如A)
葉子結點:沒有孩子結點的結點叫作葉子結點(如L、M、F)
兄弟結點:擁有相同雙親結點的所有孩子結點叫作兄弟結點(L、M是E的兄弟結點,I、J、K是D的兄弟結點)
結點的深度:是指從根節(jié)點到該節(jié)點的路徑長度(O點的深度為3,A—C—G—O)
樹的高度:是樹中所有結點高度的最大值,樹的深度是樹中所有結點深度的最大值,對于同一棵樹,其深度和高度是相同的,但是對于各個結點,其深度和高度不一定相同
二、二叉樹
二叉樹(Binary Tree)是n(n>=0)個節(jié)點的有限集合,該集合或為空集,或為由一個根節(jié)點和兩顆互不相交的,分別稱為根節(jié)點的左子樹和右子樹的二叉樹組成。
二叉樹
所有節(jié)點只有左子樹的二叉樹稱為左斜樹,只有右子樹的二叉樹稱為右斜樹。
所有節(jié)點均含左子樹和右子樹,這樣的二叉樹稱為滿二叉樹。
滿二叉樹
完全二叉樹:若設二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結點數(shù)都達到最大個數(shù),第 h 層所有的結點都連續(xù)集中在最左邊,這就是完全二叉樹。
完全二叉樹
二叉樹的應用:編譯器中的表達式樹、用于數(shù)據(jù)壓縮算法中的赫夫曼編碼樹、支持在集合中查找、插入和刪除,其平均時間復雜度為O(lognn)的二叉搜索樹(BST)、優(yōu)先隊列(PQ),它支持以對數(shù)時間(最壞情況下)對集合中的最小(或最大)數(shù)據(jù)元素進行搜索和刪除;
1、二叉樹的存儲結構
基本了解了二叉樹的組成后,我們學習怎么樣去存儲二叉樹,了解二叉樹的存儲結構。
1.1、滿二叉樹
存儲滿二叉樹可以使用數(shù)組,我們將上圖中的滿二叉樹存儲為數(shù)組為[A,B,C,D,E,F,G]),當然我們通過數(shù)組復原二叉樹時也可以按照順序復原二叉樹。
1.2、完全二叉樹
完全二叉樹和滿二叉樹的存儲方法相同,上圖中的完全二叉樹轉換為數(shù)組([A,B,C,D,E,F,G,H,I])(圖中最后的H為I)。
1.2、其他二叉樹
有的二叉樹既不是滿二叉樹又不是完全二叉樹該如何存儲?我們可以將缺少的二叉樹的葉子節(jié)點用一些特殊的符號存儲,將其轉換為完全二叉樹,如下圖所示。
則如上圖中的二叉樹轉換為數(shù)組([A,B,C,D,E,F,G,#.#,H,#,#,#,I,J])
2二叉樹的遍歷
二叉樹的遍歷分為前序遍歷、中序遍歷和后序遍歷
3.1 前序遍歷
先遍歷左子樹,再遍歷右子樹
2.2、 中序遍歷
從根結點開始(注意并不是先訪問根結點),中序遍歷根結點的左子樹,然后是訪問根結點,最后中序遍歷右子樹
2.3 后序遍歷
從左到右先葉子后結點的方式遍歷訪問左右子樹,最后是訪問根結點
3、實現(xiàn)二叉樹
如下,需要構建如下二叉樹,并實現(xiàn)其三種遍歷方法
/**
* 構造如下二叉樹
* A
* B C
* D E G
*
*/
import java.util.List;
/**
* 構造如下二叉樹
* A
* B C
* D E G
*/
public class BinaryTree {
TreeNode root = null;
public BinaryTree() {
root = new TreeNode(0, "A");
}
/**
* 傳統(tǒng)方法構造二叉樹
*/
public void createBinaryTree() {
TreeNode nodeB = new TreeNode(2, "B");
TreeNode nodeC = new TreeNode(3, "C");
TreeNode nodeD = new TreeNode(4, "D");
TreeNode nodeE = new TreeNode(5, "E");
TreeNode nodeF = new TreeNode(6, "F");
root.leftChild = nodeB;
root.rightChild = nodeC;
nodeB.leftChild = nodeD;
nodeB.rightChild = nodeE;
nodeC.rightChild = nodeF;
}
/**
* 出入二叉樹的數(shù)組,創(chuàng)建二叉樹
*
* @param size 二叉樹所有節(jié)點的數(shù)量和
* @param datas 二叉樹的List集合
* @return 返回創(chuàng)建的節(jié)點
*/
public TreeNode createBinerTree(int size, List datas) {
TreeNode node = null;
if (datas.size() == 0) {
return null;
}
String data = datas.get(0);
if ("#".equals(data)) {
datas.remove(0);
return node;
}
int index = size - datas.size();
node = new TreeNode(index, data);
if (index == 0) {
root = node;
}
datas.remove(0);
node.leftChild = createBinerTree(size, datas);
node.rightChild = createBinerTree(size, datas);
return node;
}
/**
* 前序遍歷
*/
public void preOrder(TreeNode node) {
if (node == null) {
return;
} else {
System.out.println("preOrder data:" + node.getData());
preOrder(node.leftChild);
preOrder(node.rightChild);
}
}
/**
* 中序遍歷
*/
public void midOrder(TreeNode node) {
if (node == null) {
return;
} else {
midOrder(node.leftChild);
System.out.println("midOrder data:" + node.getData());
midOrder(node.rightChild);
}
}
/**
* 后序遍歷
*/
public void postOrder(TreeNode node) {
if (node == null) {
return;
} else {
preOrder(node.leftChild);
preOrder(node.rightChild);
System.out.println("postOrder data:" + node.getData());
}
}
class TreeNode {
private int index;
private String data;
private TreeNode leftChild;
private TreeNode rightChild;
public TreeNode(int index, String data) {
this.index = index;
this.data = data;
}
public TreeNode getLeftChild() {
return leftChild;
}
public void setLeftChild(TreeNode leftChild) {
this.leftChild = leftChild;
}
public TreeNode getRightChild() {
return rightChild;
}
public void setRightChild(TreeNode rightChild) {
this.rightChild = rightChild;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
}
傳入數(shù)組測試
public class test {
public static void main(String[] args) {
BinaryTree binaryTree=new BinaryTree();
String data[]={"A","B","C","D","E","#","F"};
ArrayListdatas=new ArrayList<>(Arrays.asList(data));
binaryTree.createBinerTree(datas.size(), datas);
binaryTree.preOrder(binaryTree.root);
}
}
結果
preOrder data:A
preOrder data:B
preOrder data:C
preOrder data:D
preOrder data:E
preOrder data:F
三、搜索二叉樹
二叉查找樹(又:二叉搜索樹,二叉排序樹),它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小于它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大于它的根結點的值; 它的左、右子樹也分別為二叉排序樹。二叉排序樹的查找過程和次優(yōu)二叉樹類似,通常采取二叉鏈表作為二叉排序樹的存儲結構中序遍歷二叉排序樹可得到一個關鍵字的有序序列,一個無序序列可以通過構造一棵二叉排序樹變成一個有序序列,構造樹的過程即為對無序序列進行排序的過程。每次插入的新的結點都是二叉排序樹上新的葉子結點,在進行插入操作時,不必移動其它結點,只需改動某個結點的指針,由空變?yōu)榉强占纯?/p>
1、搜索二叉樹的實現(xiàn)
/**
* Author: Active_Loser
* Date: 2018/7/30 23:17
* Content: 實現(xiàn)搜索二叉樹的建立、添加、刪除等操作
*/
public class SearchBinryTree {
public TreeNode root;
public TreeNode put(int data) {
TreeNode node;
TreeNode parent = null;
if (root == null) {
node = new TreeNode(data);
root = node;
return node;
}
node = root;
while (node != null) {
parent = node;
if (data > parent.data) {
node = parent.rightChild;
} else if (data < parent.data) {
node = parent.leftChild;
} else {
return node;
}
}
node = new TreeNode(data);
if (data < parent.data) {
parent.leftChild = node;
node.parent = parent;
} else if (data > parent.data) {
parent.rightChild = node;
node.parent = parent;
}
return node;
}
public TreeNode search(int value) {
TreeNode node = root;
while (node != null && node.data != value) {
if (node.data > value) {
node = node.rightChild;
} else if (node.data < value) {
node = node.leftChild;
}
}
return node;
}
/**
* @param value 刪除的數(shù)值
* @return 返回刪除的節(jié)點
*/
public TreeNode delete(int value) {
//判斷是否包含需要刪除的數(shù)
TreeNode deleteNode = search(value);
if (null == deleteNode) {
return null;
}else {
delete(deleteNode);
}
}
private void delete(TreeNode node) {
if (node==null){
return null;
}
TreeNode parent=node.parent;
//做節(jié)點與有節(jié)點皆為NULL
if (node.leftChild==null&&node.rightChild==null){
if (parent.leftChild==node){
parent.leftChild=null;
}else {
parent.rightChild=null;
}
return;
}
//有左節(jié)點沒有右節(jié)點1.父節(jié)點的左節(jié)點2.父節(jié)點的右節(jié)點
if (node.leftChild!=null&&node.rightChild==null){
if (parent.leftChild==node){
parent.leftChild=node.leftChild;
}else if (parent.rightChild==node){
parent.rightChild=node.leftChild;
}
return;
}
//有右節(jié)點沒有左節(jié)點1.父節(jié)點的左節(jié)點2.父節(jié)點的右節(jié)點
if (node.leftChild!=null&&node.rightChild==null){
if (parent.leftChild==node){
parent.leftChild=node.rightChild;
}else if (parent.rightChild==node){
parent.rightChild=node.rightChild;
}
return;
}
//既有左節(jié)點也有右節(jié)點
//獲取刪除節(jié)點的后繼節(jié)點
TreeNode next=getNextNode(node);
delete(next);
node.data=next.data;
}
private TreeNode getNextNode(TreeNode node) {
if (node==null){
return null;
}else {
if (node.rightChild!=null){
return getMinTreeNode(node.rightChild);
}else {
TreeNode parent=node.parent;
while (parent!=null&&node==parent.rightChild){
node=parent;
parent=parent.parent;
}
return parent;
}
}
return null;
}
//右子樹最小值,左子樹最大值
public TreeNode getMinTreeNode(TreeNode node){
if (node==null){
return null;
}else {
while (node.leftChild !=null){
node=node.leftChild;
}
}
return node;
}
public void midOrder(TreeNode node) {
if (node == null) {
return;
} else {
midOrder(node.leftChild);
System.out.println("midOrder:" + node.data);
midOrder(node.rightChild);
}
}
class TreeNode {
private TreeNode leftChild;
private TreeNode rightChild;
private TreeNode parent;
private int data;
public TreeNode(int data) {
this.data = data;
}
public TreeNode getLeftChild() {
return leftChild;
}
public void setLeftChild(TreeNode leftChild) {
this.leftChild = leftChild;
}
public TreeNode getRightChild() {
return rightChild;
}
public void setRightChild(TreeNode rightChild) {
this.rightChild = rightChild;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
}
總結
以上是生活随笔為你收集整理的java树算法_Java数据结构算法(三)树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《世纪之石》图文流程攻略教学篇(1)
- 下一篇: java 并发 面试题_阿里面试官总结1