数据结构 - 线索化二叉树(线索化与遍历)
生活随笔
收集整理的這篇文章主要介紹了
数据结构 - 线索化二叉树(线索化与遍历)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
!!(這里我debug很久才理解過來)** 這里8的前驅為null,所以8的leftType=1,但是6是沒有后繼的或者說后繼為null但是rightType為0(因為后繼是在下一個節點來進行連接的,6沒有下一個節點,所以不能實現后繼的線索化,所以rightType=0)**
public void threadedNodes(HeroNode node){//如果node == null,就不能線索化if (node == null){return;}//(1)先線索化左子樹threadedNodes(node.getLeft());//(2)線索化當前節點//先處理當前節點的前驅節點//以8節點來理解//8節點的left = null,8節點的leftType = 1if (node.getLeft() == null){//讓當前節點的左指針指向前驅節點node.setLeft(pre);//修改當前節點的做指針的類型node.setLeftType(1);}//處理后繼節點,處理8的后繼節點,讓pre的right指向nodeif (pre != null && pre.getRight() == null){//讓前驅節點的右指針指向當前節點pre.setRight(node);//修改前驅節點的右指針類型pre.setLeftType(1);}//!!!!每處理一個節點,讓當前節點是下一個節點的前驅結點pre = node;//(3)線索化右子樹threadedNodes(node.getRight());}
完整代碼 (后序遍歷線索二叉樹沒寫出來,網上找了一些資料看完感覺還是有一點難度,暫時先不深入了)
package tree.threadedbinarytree;public class ThreadedBrinaryTreeDemo {public static void main(String[] args) {//測試中序線索二叉樹的功能HeroNode root = new HeroNode(1, "tom");HeroNode node2 = new HeroNode(3, "jack");HeroNode node3 = new HeroNode(6, "smith");HeroNode node4 = new HeroNode(8, "mary");HeroNode node5 = new HeroNode(10, "king");HeroNode node6 = new HeroNode(14, "dmi");//二叉樹,我們再遞歸創建,目前簡單手動創建root.setLeft(node2);root.setRight(node3);node2.setLeft(node4);node2.setRight(node5);node3.setLeft(node6);//測試線索化ThreadedBrinaryTree tBrinaryTree = new ThreadedBrinaryTree();tBrinaryTree.setRoot(root);tBrinaryTree.threadedNodes();//測試以10號節點做測試 // HeroNode left = node3.getLeft(); // System.out.println("10號節點的前驅節點是:"+ left); // HeroNode right = node3.getRight(); // System.out.println("10號節點的后繼節點是:"+ right);// System.out.println("使用線索化的方法中序遍歷線索化 二叉樹"); // tBrinaryTree.threadedInfixOrder();// System.out.println("使用線索化的方法前序遍歷線索化 二叉樹"); // tBrinaryTree.threadedPreOrder();} }//定義ThreadedBinaryTree class ThreadedBrinaryTree{private HeroNode root;//為了實現線索化,需要創建一個指向當前節點的前驅節點的引用//在遞歸線索化時,pre總是保留前一個節點private HeroNode pre = null;public void setRoot(HeroNode root){this.root = root;}//重載threadedNodespublic void threadedNodes(){this.threadedNodes(root);}//遍歷線索化二叉樹的前序遍歷方法public void threadedPreOrder(){HeroNode node = root;while (node != null){//打印當前節點System.out.println(node);//向左循環有前驅while(node.getLeftType() == 0){node = node.getLeft();System.out.println(node);}while (node.getRightType() == 1){node = node.getRight();}node = node.getRight();}}//遍歷線索化二叉樹的中序遍歷方法public void threadedInfixOrder(){//定義一個遍歷存儲當前遍歷的節點,從root開始HeroNode node = root;while (node != null){//循環找到lefeYype == 1的節點,第一個找到的就是8//后面隨著遍歷而變化,因為放leftType==1時說明該節點是按照線索化處理后的有效節點while (node.getLeftType() == 0){node = node.getLeft();}//打印當前節點System.out.println(node);//如果當前節點的右指針指向的是后繼節點,就一直輸出while (node.getRightType() == 1){//獲取到當前節點的后繼節點node = node.getRight();System.out.println(node);}//替換這個遍歷的節點node = node.getRight();}}//編寫對二叉樹進行中序線索化的方法public void threadedNodes(HeroNode node){//如果node == null,就不能線索化if (node == null){return;}//(1)先線索化左子樹threadedNodes(node.getLeft());//(2)線索化當前節點//先處理當前節點的前驅節點//以8節點來理解//8節點的left = null,8節點的leftType = 1if (node.getLeft() == null){//讓當前節點的左指針指向前驅節點node.setLeft(pre);//修改當前節點的做指針的類型node.setLeftType(1);}//處理后繼節點,處理8的后繼節點,讓pre的right指向nodeif (pre != null && pre.getRight() == null){//讓前驅節點的右指針指向當前節點pre.setRight(node);//修改前驅節點的右指針類型pre.setRightType(1);}//!!!!每處理一個節點,讓當前節點是下一個節點的前驅結點pre = node;//(3)線索化右子樹threadedNodes(node.getRight());}//前序遍歷public void preOrder(){if (this.root != null){this.root.preOrder();}else {System.out.println("二叉樹為空無法遍歷");}}//中序遍歷public void infixOrder(){if (this.root != null){this.root.infixOrder();}else {System.out.println("二叉樹為空無法遍歷");}}//后序遍歷public void postOrder(){if (this.root != null){this.root.postOrder();}else {System.out.println("二叉樹為空無法遍歷");}}//前序查找public HeroNode preOrederSearch(int no){if (root != null){return root.preOrderSearch(no);}else {return null;}}//中序查找public HeroNode infixOrderSeach(int no){if (root != null){return root.infixOrderSearch(no);}else {return null;}}//后序查找public HeroNode postOrderSeach(int no){if (root != null){return root.postOrderSearch(no);}else {return null;}}//刪除節點public void delNode(int no){if (root != null){//判斷root是不是要刪除的節點if (root.getNo() == no){root = null;}else {root.delNode(no);}}}} //創建節點 class HeroNode{private int no;private String name;private HeroNode left;//默認nullprivate HeroNode right;//默認null;//說明//1.如果leftType == 0 表示指向的是左子樹,如果是1表示指向前驅節點//1.如果rightType == 0 表示指向的是右子樹,如果是1表示指向后繼節點private int leftType;private int rightType;public int getLeftType() {return leftType;}public void setLeftType(int leftType) {this.leftType = leftType;}public int getRightType() {return rightType;}public void setRightType(int rightType) {this.rightType = rightType;}public HeroNode(int no, String name) {this.no = no;this.name = name;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public String getName() {return name;}public void setName(String name) {this.name = name;}public HeroNode getLeft() {return left;}public void setLeft(HeroNode left) {this.left = left;}public HeroNode getRight() {return right;}public void setRight(HeroNode right) {this.right = right;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +'}';}//編寫前序遍歷方法public void preOrder(){System.out.println(this);//先輸出父節點//遞歸向左子樹前序遍歷if (this.left != null){this.left.preOrder();}//遞歸向右子樹前序遍歷if (this.right != null){this.right.preOrder();}}//編寫中序遍歷方法public void infixOrder(){//遞歸向左子樹前序遍歷if (this.left != null){this.left.infixOrder();}System.out.println(this);//輸出父節點//遞歸向右子樹前序遍歷if (this.right != null){this.right.infixOrder();}}//編寫后序遍歷方法public void postOrder(){if (this.left != null){this.left.postOrder();}if (this.right != null){this.right.postOrder();}System.out.println(this);}public static int i = 1, j = 1, k =1;//編寫前序查找方法public HeroNode preOrderSearch(int no){System.out.println("前序遍歷"+(i++)+"次");if (this.no == no){return this;}HeroNode heroNode = null;if (this.left != null){heroNode = this.left.preOrderSearch(no);}//不等于空說明在左邊找到了if (heroNode != null){return heroNode;}if (this.right != null){heroNode = this.right.preOrderSearch(no);}return heroNode;}//中序遍歷查找public HeroNode infixOrderSearch(int no){HeroNode heroNode = null;//先判斷當前節點的左子節點是否為空,不為空繼續進行中序查找if (this.left != null){heroNode = this.left.infixOrderSearch(no);}if (heroNode != null){return heroNode;}System.out.println("中序遍歷"+(j++)+"次");if (this.no == no){return this;}if (this.right != null){heroNode = this.right.infixOrderSearch(no);}return heroNode;}//后序遍歷查找public HeroNode postOrderSearch(int no){HeroNode heroNode = null;//判斷當前節點的左子節點是否為空,不為空,則遞歸后序遍歷查找if (this.left != null){heroNode = this.left.postOrderSearch(no);}if (heroNode != null){return heroNode;}//判斷當前節點的右子節點是否為空,不為空,則遞歸后序遍歷查找if (this.right != null){heroNode = this.right.postOrderSearch(no);}if (heroNode != null){return heroNode;}System.out.println("后序遍歷"+(k++)+"次");//左右子樹都沒有找到,比較當前節點是不是if (this.no == no){return this;}return heroNode;}//遞歸刪除節點//規定:如果是葉子節點就刪除節點,如果非葉子節點就刪除子樹public void delNode(int no){if (this.left !=null && this.left.no == no){this.left = null;return;}if (this.right != null && this.right.no == no){this.right = null;return;}if (this.left != null){this.left.delNode(no);}if (this.right != null){this.right.delNode(no);}} }總結
以上是生活随笔為你收集整理的数据结构 - 线索化二叉树(线索化与遍历)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【爱心代码大全】——情人节表白代码送给她
- 下一篇: 鼻子上出的油都是哪来的?怪它 也怪你