【线索二叉树详解】数据结构06(java实现)
線索二叉樹(shù)
1. 線索二叉樹(shù)簡(jiǎn)介
定義: 在二叉樹(shù)的結(jié)點(diǎn)上加上線索的二叉樹(shù)稱為線索二叉樹(shù)。
二叉樹(shù)的線索化: 對(duì)二叉樹(shù)以某種遍歷方式(如先序、中序、后序或?qū)哟蔚?#xff09;進(jìn)行遍歷,使其變?yōu)榫€索二叉樹(shù)的過(guò)程稱為對(duì)二叉樹(shù)進(jìn)行線索化。
現(xiàn)在我們來(lái)計(jì)算一下任意一顆二叉樹(shù)有多少個(gè)空的指針域
假設(shè)有n個(gè)結(jié)點(diǎn),一個(gè)結(jié)點(diǎn)有2個(gè)指針域(指向左右子節(jié)點(diǎn)),一共就有2n個(gè)結(jié)點(diǎn)
除了第一個(gè)結(jié)點(diǎn)不需要父節(jié)點(diǎn)指向,其余所有節(jié)點(diǎn)均需要指針,所以有n-1個(gè)已經(jīng)使用的指針域
剩下:2*n-(n-1)=n+1
結(jié)論:任意二叉樹(shù)的空余指針域?yàn)閚+1
如上圖所示:紅線就是將二叉樹(shù)線索化變成線索二叉樹(shù)的過(guò)程。
通俗的講:將普通二叉樹(shù)的空余指針域都利用起來(lái),指向其前驅(qū)結(jié)點(diǎn)或后繼結(jié)點(diǎn)就變成了線索二叉樹(shù)
2. 線索二叉樹(shù)的實(shí)現(xiàn)
2.1 實(shí)現(xiàn)思路
首先我們需要選擇線索化二叉樹(shù)的方式-這里我們使用中序線索化二叉樹(shù)
在遍歷每個(gè)節(jié)點(diǎn)時(shí),判斷結(jié)點(diǎn)的左子節(jié)點(diǎn)和右子節(jié)點(diǎn)是否為空(也就是左右指針域)
如果左子節(jié)點(diǎn)為空就將其指向當(dāng)前結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)
如果右子節(jié)點(diǎn)為空就指向后繼結(jié)點(diǎn)(這里的前驅(qū)、后繼結(jié)點(diǎn)是相對(duì)于遍歷方式而言)
相比普通二叉樹(shù)我們?cè)黾觾蓚€(gè)標(biāo)志位:leftType、rightType
2.2 實(shí)現(xiàn)代碼
二叉樹(shù)結(jié)點(diǎn)類:ThreadedBinaryNode.java
//中序線索二叉樹(shù) public class ThreadedBinaryNode {//結(jié)點(diǎn)的值int value;//左節(jié)點(diǎn)ThreadedBinaryNode leftNode;//右節(jié)點(diǎn)ThreadedBinaryNode rightNode;//線索二叉樹(shù)增加的兩個(gè)屬性//1代表存儲(chǔ)的是前驅(qū)、后續(xù)結(jié)點(diǎn)。0代表左右兒子(默認(rèn)為0)int leftType,rightType;//初始化值public ThreadedBinaryNode(int value){this.value=value;}//設(shè)置左節(jié)點(diǎn)public void setLeftNode(ThreadedBinaryNode leftNode) {this.leftNode = leftNode;}//設(shè)置右節(jié)點(diǎn)public void setRightNode(ThreadedBinaryNode rightNode) {this.rightNode = rightNode;} }線索二叉樹(shù)類:ThreadedBinaryTree.java
增加了一個(gè)存儲(chǔ)前驅(qū)結(jié)點(diǎn)的pre,主要實(shí)現(xiàn)中序線索化的threadedMid方法,遍歷方法threadedIterate
public class ThreadedBinaryTree {//根節(jié)點(diǎn)ThreadedBinaryNode root;//存儲(chǔ)前序結(jié)點(diǎn)ThreadedBinaryNode pre=null;//設(shè)置根節(jié)點(diǎn)、獲取根節(jié)點(diǎn)public ThreadedBinaryNode getRoot() {return root;}public void setRoot(ThreadedBinaryNode root) {this.root = root;}//遍歷中序化線索二叉樹(shù)public void threadedIterate(){ThreadedBinaryNode node=root;while(node!=null){//先找到中序遍歷最左邊的結(jié)點(diǎn)while(node.leftType==0){node=node.leftNode;}System.out.print(node.value+" ");//遍歷右指針域指向后繼基點(diǎn)的結(jié)點(diǎn)while(node.rightType==1){node=node.rightNode;System.out.print(node.value+" ");}//替換遍歷結(jié)點(diǎn)node=node.rightNode;}}//方便調(diào)用public void threadedMid(){threadedMid(root);}//中序線索化二叉樹(shù)-將左右指針域?yàn)榭盏臉?biāo)記1,不為空(指向左右兒子)的默認(rèn)為0public void threadedMid(ThreadedBinaryNode node){if(node==null)return;//遞歸處理左子樹(shù)threadedMid(node.leftNode);//處理當(dāng)前結(jié)點(diǎn)的左指針域if(node.leftNode==null){//將當(dāng)前結(jié)點(diǎn)的左指針域指向前序結(jié)點(diǎn)node.leftNode=pre;//標(biāo)記node.leftType=1;}//處理前驅(qū)結(jié)點(diǎn)pre的右指針域//因?yàn)檫@里拿不到當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn),所以不能處理當(dāng)前節(jié)點(diǎn)的右指針域if(pre!=null&&pre.rightNode==null){//如果pre的右指針為空,就指向他的后繼結(jié)點(diǎn)-nodepre.rightNode=node;pre.rightType=1;}//保存當(dāng)前結(jié)點(diǎn),為下一結(jié)點(diǎn)的prepre=node;//遞歸處理右子樹(shù)threadedMid(node.rightNode);} }測(cè)試類
public class TestThreadedTree {public static void main(String[] args) {//創(chuàng)建一顆空二叉樹(shù)ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();//創(chuàng)建根結(jié)點(diǎn)ThreadedBinaryNode root=new ThreadedBinaryNode(1);threadedBinaryTree.setRoot(root);//創(chuàng)建根結(jié)點(diǎn)的左節(jié)點(diǎn)和右節(jié)點(diǎn)ThreadedBinaryNode leftNode = new ThreadedBinaryNode(2);ThreadedBinaryNode rightNode = new ThreadedBinaryNode(3);//將左右結(jié)點(diǎn)連接在根結(jié)點(diǎn)后root.setLeftNode(leftNode);root.setRightNode(rightNode);//增加四個(gè)節(jié)點(diǎn) 4、5、6、7方便遍歷leftNode.setLeftNode(new ThreadedBinaryNode(4));leftNode.setRightNode(new ThreadedBinaryNode(5));rightNode.setLeftNode(new ThreadedBinaryNode(6));rightNode.setRightNode(new ThreadedBinaryNode(7));//中序線索化二叉樹(shù)threadedBinaryTree.threadedMid();//遍歷中序線索二叉樹(shù)System.out.println("遍歷中序線索二叉樹(shù)結(jié)果為:");threadedBinaryTree.threadedIterate();} }結(jié)果:
遍歷中序線索二叉樹(shù)結(jié)果為: 4 2 5 1 6 3 73. 總結(jié):
線索二叉樹(shù)減少了的空指針域的同時(shí)又對(duì)每個(gè)節(jié)點(diǎn)增加了兩個(gè)標(biāo)志位。好處:在遍歷時(shí)不需要使用遞歸,相比普通二叉樹(shù)遍歷效率更高在查找前驅(qū)/后繼結(jié)點(diǎn)時(shí)更加高效4. 應(yīng)用
當(dāng)路由器使用CIDR,選擇下一跳的時(shí)候,或者轉(zhuǎn)發(fā)分組的時(shí)候,通常會(huì)用最長(zhǎng)前綴匹配(最佳匹配)來(lái)得到路由表的一行數(shù)據(jù),為了更加有效的查找最長(zhǎng)前綴匹配,通常使用的數(shù)據(jù)結(jié)構(gòu)為二叉線索。
總結(jié)
以上是生活随笔為你收集整理的【线索二叉树详解】数据结构06(java实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【二叉树详解】二叉树的创建、遍历、查找以
- 下一篇: 【赫夫曼树详解】赫夫曼树简介及java代