数据结构 - 线索化二叉树(线索化与遍历)
生活随笔
收集整理的這篇文章主要介紹了
数据结构 - 线索化二叉树(线索化与遍历)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
!!(這里我debug很久才理解過來)** 這里8的前驅(qū)為null,所以8的leftType=1,但是6是沒有后繼的或者說后繼為null但是rightType為0(因為后繼是在下一個節(jié)點來進(jìn)行連接的,6沒有下一個節(jié)點,所以不能實現(xiàn)后繼的線索化,所以rightType=0)**
public void threadedNodes(HeroNode node){//如果node == null,就不能線索化if (node == null){return;}//(1)先線索化左子樹threadedNodes(node.getLeft());//(2)線索化當(dāng)前節(jié)點//先處理當(dāng)前節(jié)點的前驅(qū)節(jié)點//以8節(jié)點來理解//8節(jié)點的left = null,8節(jié)點的leftType = 1if (node.getLeft() == null){//讓當(dāng)前節(jié)點的左指針指向前驅(qū)節(jié)點node.setLeft(pre);//修改當(dāng)前節(jié)點的做指針的類型node.setLeftType(1);}//處理后繼節(jié)點,處理8的后繼節(jié)點,讓pre的right指向nodeif (pre != null && pre.getRight() == null){//讓前驅(qū)節(jié)點的右指針指向當(dāng)前節(jié)點pre.setRight(node);//修改前驅(qū)節(jié)點的右指針類型pre.setLeftType(1);}//!!!!每處理一個節(jié)點,讓當(dāng)前節(jié)點是下一個節(jié)點的前驅(qū)結(jié)點pre = node;//(3)線索化右子樹threadedNodes(node.getRight());}
完整代碼 (后序遍歷線索二叉樹沒寫出來,網(wǎng)上找了一些資料看完感覺還是有一點難度,暫時先不深入了)
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");//二叉樹,我們再遞歸創(chuàng)建,目前簡單手動創(chuàng)建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號節(jié)點做測試 // HeroNode left = node3.getLeft(); // System.out.println("10號節(jié)點的前驅(qū)節(jié)點是:"+ left); // HeroNode right = node3.getRight(); // System.out.println("10號節(jié)點的后繼節(jié)點是:"+ right);// System.out.println("使用線索化的方法中序遍歷線索化 二叉樹"); // tBrinaryTree.threadedInfixOrder();// System.out.println("使用線索化的方法前序遍歷線索化 二叉樹"); // tBrinaryTree.threadedPreOrder();} }//定義ThreadedBinaryTree class ThreadedBrinaryTree{private HeroNode root;//為了實現(xiàn)線索化,需要創(chuàng)建一個指向當(dāng)前節(jié)點的前驅(qū)節(jié)點的引用//在遞歸線索化時,pre總是保留前一個節(jié)點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){//打印當(dāng)前節(jié)點System.out.println(node);//向左循環(huán)有前驅(qū)while(node.getLeftType() == 0){node = node.getLeft();System.out.println(node);}while (node.getRightType() == 1){node = node.getRight();}node = node.getRight();}}//遍歷線索化二叉樹的中序遍歷方法public void threadedInfixOrder(){//定義一個遍歷存儲當(dāng)前遍歷的節(jié)點,從root開始HeroNode node = root;while (node != null){//循環(huán)找到lefeYype == 1的節(jié)點,第一個找到的就是8//后面隨著遍歷而變化,因為放leftType==1時說明該節(jié)點是按照線索化處理后的有效節(jié)點while (node.getLeftType() == 0){node = node.getLeft();}//打印當(dāng)前節(jié)點System.out.println(node);//如果當(dāng)前節(jié)點的右指針指向的是后繼節(jié)點,就一直輸出while (node.getRightType() == 1){//獲取到當(dāng)前節(jié)點的后繼節(jié)點node = node.getRight();System.out.println(node);}//替換這個遍歷的節(jié)點node = node.getRight();}}//編寫對二叉樹進(jìn)行中序線索化的方法public void threadedNodes(HeroNode node){//如果node == null,就不能線索化if (node == null){return;}//(1)先線索化左子樹threadedNodes(node.getLeft());//(2)線索化當(dāng)前節(jié)點//先處理當(dāng)前節(jié)點的前驅(qū)節(jié)點//以8節(jié)點來理解//8節(jié)點的left = null,8節(jié)點的leftType = 1if (node.getLeft() == null){//讓當(dāng)前節(jié)點的左指針指向前驅(qū)節(jié)點node.setLeft(pre);//修改當(dāng)前節(jié)點的做指針的類型node.setLeftType(1);}//處理后繼節(jié)點,處理8的后繼節(jié)點,讓pre的right指向nodeif (pre != null && pre.getRight() == null){//讓前驅(qū)節(jié)點的右指針指向當(dāng)前節(jié)點pre.setRight(node);//修改前驅(qū)節(jié)點的右指針類型pre.setRightType(1);}//!!!!每處理一個節(jié)點,讓當(dāng)前節(jié)點是下一個節(jié)點的前驅(qū)結(jié)點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;}}//刪除節(jié)點public void delNode(int no){if (root != null){//判斷root是不是要刪除的節(jié)點if (root.getNo() == no){root = null;}else {root.delNode(no);}}}} //創(chuàng)建節(jié)點 class HeroNode{private int no;private String name;private HeroNode left;//默認(rèn)nullprivate HeroNode right;//默認(rèn)null;//說明//1.如果leftType == 0 表示指向的是左子樹,如果是1表示指向前驅(qū)節(jié)點//1.如果rightType == 0 表示指向的是右子樹,如果是1表示指向后繼節(jié)點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);//先輸出父節(jié)點//遞歸向左子樹前序遍歷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);//輸出父節(jié)點//遞歸向右子樹前序遍歷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;//先判斷當(dāng)前節(jié)點的左子節(jié)點是否為空,不為空繼續(xù)進(jìn)行中序查找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;//判斷當(dāng)前節(jié)點的左子節(jié)點是否為空,不為空,則遞歸后序遍歷查找if (this.left != null){heroNode = this.left.postOrderSearch(no);}if (heroNode != null){return heroNode;}//判斷當(dāng)前節(jié)點的右子節(jié)點是否為空,不為空,則遞歸后序遍歷查找if (this.right != null){heroNode = this.right.postOrderSearch(no);}if (heroNode != null){return heroNode;}System.out.println("后序遍歷"+(k++)+"次");//左右子樹都沒有找到,比較當(dāng)前節(jié)點是不是if (this.no == no){return this;}return heroNode;}//遞歸刪除節(jié)點//規(guī)定:如果是葉子節(jié)點就刪除節(jié)點,如果非葉子節(jié)點就刪除子樹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);}} }總結(jié)
以上是生活随笔為你收集整理的数据结构 - 线索化二叉树(线索化与遍历)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【爱心代码大全】——情人节表白代码送给她
- 下一篇: volatile学习(可见性,不保证原子