树-志宇
樹
二叉樹
---- 二叉樹的遍歷,添加,查找,刪除
---- 順序存儲(chǔ)二叉樹
-----線索化二叉樹
赫夫曼樹
赫夫曼編碼
二叉排序樹
平衡二叉樹中的AVL數(shù)
二叉樹
完全二叉樹:
一個(gè)二叉樹,如果每一個(gè)層的結(jié)點(diǎn)數(shù)都達(dá)到最大值,則這個(gè)二叉樹就是滿二叉樹。也就是說,如果一個(gè)二叉樹的層數(shù)為K,且結(jié)點(diǎn)總數(shù)是(2^k) -1 ,則它就是滿二叉樹
滿二叉樹:
若設(shè)二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個(gè)數(shù),第 h 層所有的結(jié)點(diǎn)都連續(xù)集中在最左邊,這就是完全二叉樹
二叉樹的遍歷,添加,查找,刪除
代碼
public class BinaryTreeDemo{public static void main(String[] args) {TreeNode root=new TreeNode(1);TreeNode node1=new TreeNode(2);root.setLeft(node1);TreeNode node2=new TreeNode(3);root.setRight(node2);TreeNode node3=new TreeNode(4);node1.setLeft(node3);TreeNode node4=new TreeNode(5);node1.setRight(node4);TreeNode node5=new TreeNode(6);node2.setLeft(node5);TreeNode node6=new TreeNode(7);node2.setRight(node6);TreeNode node7=new TreeNode(8);node3.setLeft(node7);TreeNode node8=new TreeNode(9);node3.setRight(node8);BinaryTree binaryTree = new BinaryTree(root);//前序遍歷輸出//binaryTree.preOrder();//中序遍歷輸出//binaryTree.infixOrder();//后序遍歷輸出//binaryTree.postOrder();//前序遍歷查找// TreeNode tree = binaryTree.preOrderSearch(8);// System.out.println(tree);//中序遍歷查找//TreeNode tree = binaryTree.infixOrderSearch(1);//System.out.println(tree.getNo());//后序遍歷查找//TreeNode tree = binaryTree.postOrderSearch(0);//System.out.println(tree.getNo());//節(jié)點(diǎn)刪除,如果刪除的是非葉子節(jié)點(diǎn),將非葉子節(jié)點(diǎn)下的節(jié)點(diǎn)也刪除//binaryTree.deleteTree(node5);//binaryTree.preOrder();//節(jié)點(diǎn)刪除,如果刪除的是非葉子節(jié)點(diǎn),只刪除此節(jié)點(diǎn),此節(jié)點(diǎn)的左節(jié)點(diǎn)代替它binaryTree.deleteNode(node1);binaryTree.preOrder();} } class BinaryTree{private TreeNode root;public BinaryTree(TreeNode root) {this.root=root;}//刪除節(jié)點(diǎn)node,然后node節(jié)點(diǎn)的左子節(jié)點(diǎn)代替nodepublic void deleteNode(TreeNode node5) {if(root !=null){if(this.root.getNo()==node5.getNo()){//1.首先緩存根節(jié)點(diǎn)的右節(jié)點(diǎn)(tempNode)//2.如果根節(jié)點(diǎn)沒有左子節(jié)點(diǎn),則將右節(jié)點(diǎn)設(shè)置為根節(jié)點(diǎn)結(jié)束//3.如果根節(jié)點(diǎn)有左子節(jié)點(diǎn),則將左子節(jié)點(diǎn)設(shè)置為根節(jié)點(diǎn)(leftRoot)//4.如果tempNode為null則直接結(jié)束,否則進(jìn)行如下操作//5.如果leftRoot有沒有左子節(jié)點(diǎn),則將tempNode設(shè)置為leftRoot的左子節(jié)點(diǎn)//6.如果leftRoot有沒有右子節(jié)點(diǎn),則將tempNode設(shè)置為leftRoot的右子節(jié)點(diǎn)//7.如果leftRoot有左子節(jié)點(diǎn)和又子節(jié)點(diǎn)則作如下操作//8. // 緩存根節(jié)點(diǎn) // TreeNode temp=leftRoot; // 緩存根節(jié)點(diǎn)的右節(jié)點(diǎn) // TreeNode rightTemp=null; // 只要他的右子節(jié)點(diǎn)不為空 // while(temp.right!=null){ // 緩存兩個(gè)值,同時(shí)給 // rightTemp=temp.right; // temp.right=tempNode; // tempNode=rightTemp; // 節(jié)點(diǎn)后移 // temp=temp.left; // } // 他的右子節(jié)點(diǎn)為空時(shí),將值設(shè)置為他的父節(jié)點(diǎn)的右子節(jié)點(diǎn) // temp.setRight(tempNode);}else{this.root.deleteNode(node5); }}}//刪除以node5為根節(jié)點(diǎn)的樹public void deleteTree(TreeNode node5) {if(root.getNo()==node5.getNo()){this.root=null;return;}root.deleteTree(node5);}//后序遍歷查找public TreeNode postOrderSearch(int i) {return root.postOrderSearch(i);}//中序遍歷查找public TreeNode infixOrderSearch(int i) {return root.infixOrderSearch(i);}//前序遍歷查找public TreeNode preOrderSearch(int i) {return this.root.preOrderSerach(i); }//前序遍歷//中->左->右public void preOrder() {if(root!=null){root.preOrder();}}//中序遍歷//左->中->右public void infixOrder(){if(root!=null){root.infixOrder();}}//后序遍歷//左->右->中public void postOrder(){if(root!=null){root.postOrder();}}} class TreeNode{private int no;private TreeNode left;private TreeNode right;public TreeNode(int no) {this.no=no;}//刪除node節(jié)點(diǎn)public void deleteNode(TreeNode node) {if(this.left!=null && this.left.getNo()==node.getNo()){//這時(shí)要?jiǎng)h除this.left節(jié)點(diǎn)//1.如果this.left有右節(jié)點(diǎn) 緩存this.left的左子節(jié)點(diǎn)TreeNode rightNode=null;if(this.left.right!=null){rightNode=this.left.right;}//刪除left節(jié)點(diǎn),如果left有子節(jié)點(diǎn),將left的左子節(jié)點(diǎn)代替它if(this.left.left==null){this.setLeft(rightNode);}else{//要?jiǎng)h除的孩子的節(jié)點(diǎn)有值this.setLeft(this.left.left);//當(dāng)替換的節(jié)點(diǎn)沒有右節(jié)點(diǎn)時(shí)直接將緩存的節(jié)點(diǎn)添加上if(rightNode!=null){if(this.left.right==null){this.left.right=rightNode;}else if(this.left.left==null){this.left.left=rightNode;}else{//緩存刪除節(jié)點(diǎn)位置上的節(jié)點(diǎn)TreeNode temp=this.left;//緩存刪除節(jié)點(diǎn)位置的右節(jié)點(diǎn)TreeNode temp2=null;while(temp.right!=null){temp2=temp.right;temp.right=rightNode;rightNode=temp2;temp=temp.left;}temp.setRight(rightNode);}}}}if(this.right!=null && this.right.getNo()==node.getNo()){//同left 代碼略}if(this.left!=null){this.left.deleteNode(node);}if(this.right!=null){this.right.deleteNode(node);}}//刪除以node為根節(jié)點(diǎn)的樹public void deleteTree(TreeNode node5) { // if(this.getNo()==node5.getNo()){ // this=null; 這里不能設(shè)置要在調(diào)用方法中設(shè)置 // }if(this.getLeft()!=null && this.getLeft().getNo() == node5.getNo()){this.setLeft(null);}if(this.getRight()!=null && this.getRight().getNo() == node5.getNo()){this.setRight(null);}if(this.getLeft()!=null){this.getLeft().deleteTree(node5);}if(this.getRight()!=null){this.getRight().deleteTree(node5);}}public TreeNode postOrderSearch(int i) {TreeNode treeNode=null;if(this.left!=null){treeNode=this.left.postOrderSearch(i);}if(this.right!=null){treeNode=this.right.postOrderSearch(i);}if(this.no==i){return this;}return treeNode;}public TreeNode infixOrderSearch(int i) {TreeNode treeNode=null;if(this.left !=null){treeNode=this.left.infixOrderSearch(i);}if(treeNode!=null){return treeNode;}if(this.no==i){return this;}if(this.right !=null){treeNode=this.right.infixOrderSearch(i);}return treeNode;}//前序遍歷查找public TreeNode preOrderSerach(int i) {if(this.no==i)return this;//用來返回,如果沒有找到就返回這個(gè)nullTreeNode treeNode = null;if(this.left!=null)treeNode=this.left.preOrderSerach(i);if(treeNode != null){return treeNode;}if(this.right!=null)treeNode=this.right.preOrderSerach(i);return treeNode;}//后序遍歷public void postOrder() {if(this.getLeft()!=null){this.getLeft().postOrder();}if(this.getRight()!=null){this.getRight().postOrder();}System.out.println(this.no);}//中序遍歷public void infixOrder() {if(this.getLeft()!=null){this.left.infixOrder();}System.out.println(this.no);if(this.getRight()!=null){this.right.infixOrder();}}//前序遍歷public void preOrder() {System.out.println(this.getNo());if(this.getLeft()!=null){this.getLeft().preOrder();}if(this.getRight()!=null){this.getRight().preOrder();}}public int getNo() {return no;}public TreeNode getLeft() {return left;}public TreeNode getRight() {return right;}public void setNo(int no) {this.no = no;}public void setLeft(TreeNode left) {this.left = left;}public void setRight(TreeNode right) {this.right = right;} }順序存儲(chǔ)二叉樹
思想
從數(shù)據(jù)存儲(chǔ)來看,數(shù)組存儲(chǔ)方式和樹的存儲(chǔ)方式可以相互轉(zhuǎn)換,即數(shù)組可以轉(zhuǎn)換成樹,樹也可以轉(zhuǎn)換成數(shù)組。
順序存儲(chǔ)二叉樹的特點(diǎn):
順序二叉樹通常只考慮完全二叉樹
第n個(gè)元素的左子節(jié)點(diǎn)為 2 * n + 1
第n個(gè)元素的右子節(jié)點(diǎn)為 2 * n + 2
第n個(gè)元素的父節(jié)點(diǎn)為 (n-1) / 2
最后一個(gè)葉子節(jié)點(diǎn)為 數(shù)組長(zhǎng)度/2-1
代碼
線索化二叉樹
思想
線索化二叉樹 本質(zhì)上是將 一個(gè)復(fù)雜的非線性結(jié)構(gòu)轉(zhuǎn)換為線性結(jié)構(gòu),使每個(gè)結(jié)點(diǎn)都有了唯一前驅(qū)和后繼節(jié)點(diǎn)
優(yōu)點(diǎn)
(1)利用線索二叉樹進(jìn)行中序遍歷時(shí),不必采用堆棧處理,速度較一般二叉樹的遍歷速度快,且節(jié)約存儲(chǔ)空間(使用while循環(huán)即可遍歷樹,不用遞歸調(diào)用了)
(2)任意一個(gè)結(jié)點(diǎn)都能直接找到它的前驅(qū)和后繼結(jié)點(diǎn)
缺點(diǎn)
(1)結(jié)點(diǎn)的插入和刪除麻煩,且速度也較慢
(2)線索子樹不能共用
圖解
代碼
赫夫曼樹
思想
給定n個(gè)權(quán)值作為n個(gè)葉子結(jié)點(diǎn),構(gòu)造一棵二叉樹,若該樹的帶權(quán)路徑長(zhǎng)度(wpl)達(dá)到最小,稱這樣的二叉樹為赫夫曼樹
權(quán)值較大的結(jié)點(diǎn)離根較近,權(quán)值較小的結(jié)點(diǎn)離根較遠(yuǎn)(權(quán)值一般為節(jié)點(diǎn)出現(xiàn)個(gè)數(shù))
代碼
赫夫曼編碼
思想
代碼
二叉排序樹
思想
一棵空樹,或者是具有下列性質(zhì)的二叉樹:
(1)若左子樹不空,則左子樹上所有結(jié)點(diǎn)的值均小于它的根結(jié)點(diǎn)的值;
(2)若右子樹不空,則右子樹上所有結(jié)點(diǎn)的值均大于它的根結(jié)點(diǎn)的值;
(3)左、右子樹也分別為二叉排序樹;
(4)沒有鍵值相等的結(jié)點(diǎn)。
平衡二叉樹中的AVL樹
思想
代碼
總結(jié)
- 上一篇: 高等数学公式大赏
- 下一篇: java 开源项目(大汇总)