日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java实现前中后序线索化二叉树以及遍历

發布時間:2025/3/21 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java实现前中后序线索化二叉树以及遍历 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 一、線索化二叉樹的原理
    • 二、構建線索化二叉樹
    • 三、代碼實現線索二叉樹

一、線索化二叉樹的原理

在前面介紹二叉樹的文章中提到,二叉樹可以使用兩種存儲結構:順序存儲和鏈式存儲,在使用鏈式存儲時,會存在大量的空指針域,n個節點的二叉鏈表中含有n+1[ 2n-(n-1)=n+1 ]個空指針域,為了可以充分利用這些空指針域,引申出了線索化二叉樹,將這些空指針域利用起來,提高檢索效率。

上圖中,紫色區域就是沒有指向的空指針域,從存儲空間的角度來看,這些空指針域浪費了內存資源。

從另外的角度思考,如果需要知道C節點的前驅節點和后繼節點,每次都都需要進行一次遍歷,是否可以提前存儲C節點的前驅節點和后繼節點從而省去遍歷的操作從而提高效率呢?

綜合以上分析,可以通過充分利用二叉鏈表中的空指針域,存入節點在某種遍歷方式下的前驅和后繼節點的指針。

這種指向前驅和后繼的指針成為線索,加上線索的二叉鏈成為線索鏈表,而對應的二叉樹就稱為線索化二叉樹(Threaded Binary Tree)


二、構建線索化二叉樹

  • 先對二叉樹進行中序遍歷(不了解二叉樹遍歷的可以參考數據結構:二叉樹),將所有節點右指針為空的指針域指針它的后繼節點,如下圖:

通過中序遍歷到D節點,得到了D節點right指針為空,并且D節點后繼節點為B,于是將D的right節點指向B節點(如上圖中的①操作),而B節點right指針也為空,于是將right指針指向A節點(如上圖中的②操作),以此類推,到F節點的后繼節點為Null,則F的right指針指向Null。

  • 接下來將這顆二叉樹所有左指針為空的指針指向它的前驅節點,如下圖:

    如上圖,D節點的left指針域指向Null(第⑤部操作),E節點的前驅節點是A,將E的left指針指向A節點,以此類推,F節點的left節點指向C節點。

  • 通過上述兩步操作完成了整個二叉樹的線索化。

通過線索化后,可以看出(藍色箭頭表示前驅,粉色箭頭表示后繼)線索化二叉樹相當于是把二叉樹轉換成一個特殊的雙向鏈表,這樣對新增、刪除以及查找節點都帶來了方便,提高了效率,轉換為鏈表后的圖示如下:

線索化需要對節點的結構進行修改,修改之后的數據結構如下:

class Node {private int num;private Object data; //數據域private Node left; //左指針域private Node right; //右指針域/*** leftType == 0表示指向的是左子樹,如果是1表示指向前驅節點*/private int leftType;/*** rightType == 0表示指向的是右子樹,如果是1表示指向后繼節點*/private int rightType; }

三、代碼實現線索二叉樹

  • 節點結構

    class Node {private int num;private Object data;private Node left;private Node right;/*** leftType == 0表示指向的是左子樹,如果是1表示指向前驅節點*/private int leftType;/*** rightType == 0表示指向的是右子樹,如果是1表示指向后繼節點*/private int rightType;public Node(int num, Object data){this.num = num;this.data = data;}/*** 前序遍歷*/public void preOrder(){//先輸出父節點信息System.out.println(this);//判斷此節點的左節點是否為空//如果左節點不為空并且指針類型不是前驅類型if (this.left != null && this.leftType != 1){//向左前序遍歷this.left.preOrder();}//判斷此節點的右節點是否為空//如果右節點不為空并且指針類型不是后繼類型if (this.right != null && this.rightType != 1){//向右前序遍歷this.right.preOrder();}}/*** 中序遍歷線索化二叉樹*/public void infixOrder(){//判斷此節點的左節點是否為空if (this.left != null && this.leftType != 1){//向左中序遍歷this.left.infixOrder();}//輸出父節點信息System.out.println(this);//判斷此節點的右節點是否為空if (this.right != null && this.rightType != 1){//向右中序遍歷this.right.infixOrder();}}/*** 后序遍歷*/public void postOrder(){//判斷此節點的左節點是否為空if (this.left != null && this.leftType != 1){//向左后序遍歷this.left.postOrder();}//判斷此節點的右節點是否為空if (this.right != null && this.rightType != 1){//向右后序遍歷this.right.postOrder();}//輸出父節點信息System.out.println(this);}//get set方法省略@Overridepublic String toString(){return "Node{" +"num=" + num +", data=" + data +'}';} }
  • 線索化二叉樹結構

    /*** 定義ThreadedBinaryTree 實現了線索化功能的二叉樹*/ class ThreadedBinaryTree {/*** 根節點*/private Node root;/*** 為了實現線索化,需要創建要指向當前節點的前驅節點的指針* 在遞歸進行線索化時,pre總是保留前一個節點*/private Node pre = null;public void setRoot(Node root){this.root = root;}public void createBinaryTree(ArrayList<Node> list){this.createBinaryTree(list,0);}/*** 創建二叉樹* @param list 節點列表* @param index 用于創建的索引* @return*/private Node createBinaryTree(ArrayList<Node> list, int index){Node node = null;if (isEmpty()){setRoot(list.get(0));}if (index < list.size()){node = list.get(index);node.setLeft(createBinaryTree(list, (2*index+1)));node.setRight(createBinaryTree(list, (2*index+2)));}return node;}public boolean isEmpty(){return root == null;}public void preThreadNodes(){this.preThreadNodes(root);}public void infixThreadNodes(){this.infixThreadNodes(root);}public void postThreadNodes(){this.postThreadNodes(root);}/*** 前序線索化二叉樹* @param node 當前需要線索化的節點*/private void preThreadNodes(Node node){//遞歸回溯條件if (node == null){return;}//遍歷到葉子節點(前驅指針未利用)if (node.getLeft() == null){node.setLeft(pre);node.setLeftType(1);}//pre.getLeft() != node 一定不可少//否則在第一次回溯后到父節點后,如果不加上此判斷會讓pre節點后驅指針指向該父節點//此時pre的前驅后繼節點均指向該父節點,必然會發生死循環無法結束遞歸if (pre != null && pre.getRight() == null && pre.getLeft() != node){pre.setRight(node);pre.setRightType(1);}pre = node;if (node.getLeftType() == 0){preThreadNodes(node.getLeft());}preThreadNodes(node.getRight());}/*** 中序線索化二叉樹* @param node 當前需要線索化的節點*/private void infixThreadNodes(Node node){if (node == null){return;}//1.遞歸線索化左子樹infixThreadNodes(node.getLeft());//2.線索化當前節點//處理當前節點的前驅節點if (node.getLeft() == null){//讓當前節點的左指針指向前驅節點node.setLeft(pre);//修改當前節點的左指針的類型node.setLeftType(1);}//處理后繼節點if (pre != null && pre.getRight() == null){//讓前驅節點的右指針指向當前節點pre.setRight(node);//修改前驅節點的右指針類型pre.setRightType(1);}//每處理一個節點之后讓當前節點是下一個節點的前驅節點pre = node;//3.遞歸線索化右子樹infixThreadNodes(node.getRight());}/*** 后序線索化二叉樹* @param node 當前需要線索化的節點*/private void postThreadNodes(Node node){if (node == null){return;}postThreadNodes(node.getLeft());postThreadNodes(node.getRight());if (node.getLeft() == null){node.setLeft(pre);node.setLeftType(1);}if ( pre!= null && pre.getRight() == null ){pre.setRight(node);pre.setRightType(1);}pre = node;}/*** 非遞歸方式中序遍歷線索化二叉樹的方法*/public void threadedInfixList(){Node node = root;while (node != null){//循環地找到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 threadedTreePreList(){if (root != null){root.preOrder();}else{System.out.println("二叉樹為空,無法遍歷");}}public void threadedTreeInfixList(){if (root != null){root.infixOrder();}else{System.out.println("二叉樹為空,無法遍歷");}}public void threadedTreePostList(){if (root != null){root.postOrder();}else{System.out.println("二叉樹為空,無法遍歷");}} }

以上。

如有不足或者錯誤歡迎評論指正。

整理不易,留個三連再走吧!

總結

以上是生活随笔為你收集整理的Java实现前中后序线索化二叉树以及遍历的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲欧美一区二区三区在线 | 久久综合伊人77777蜜臀 | 午夜国产在线视频 | 打屁股无遮挡网站 | 午夜不卡影院 | 久久久久xxxx | 久久久久久久黄色片 | 日韩大片一区 | 夜夜夜影院| 久操新在线| 免费毛片视频网站 | 豆豆色成人网 | 精品黑人一区二区三区久久 | 久久久午夜视频 | 果冻av在线 | 国产亚洲精品久久久久久777 | a少妇| 最好看的中文字幕国语电影mv | 丁香花完整视频在线观看 | 日韩欧美一区二区三区视频 | 免费一级特黄特色大片 | 久久精品国产网红主播 | 国产一区二区免费在线 | 日韩激情一区二区三区 | 亚洲人天堂 | 91丨九色丨蝌蚪丨对白 | 9久9久9久女女女九九九一九 | a级欧美 | 男人爆操女人 | 久久久久免费 | 香蕉久久a毛片 | 先锋久久 | 超碰在线超碰 | 黄网在线免费观看 | 国产中文在线观看 | 伊人91视频 | 天堂av在线免费观看 | 4色av| 久久中文字幕一区二区 | 欧美最顶级a∨艳星 | 激情宗合 | 免费观看黄色网页 | 国产馆视频 | 成人性做爰aaa片免费看不忠 | 性做久久久久久久久久 | 国产高清视频 | 99性趣网| 91色国产 | 中文在线а√天堂 | 粉嫩av一区二区三区 | 国产精品免费网站 | 国产精品国产一区二区 | 国产精品1024 | 久久综合九色综合欧美狠狠 | 中文字幕第12页 | 午夜国产片 | 18禁裸乳无遮挡啪啪无码免费 | 樱桃视频污污 | 在线视频97 | 秋霞国产一区 | 国产一级做a爱免费视频 | 午夜国产| 久久久久中文字幕 | 欧美成人91 | 超碰在线成人 | 国产女人视频 | 亚洲 国产 欧美 日韩 | 日本黄色视屏 | 黄色片的网站 | 秋葵视频在线 | 好吊妞这里只有精品 | 免费av大全| 午夜亚洲AV永久无码精品蜜芽 | 毛片视频网站在线观看 | 狠狠干在线视频 | 久久精品4| 人妻精品无码一区二区三区 | 午夜免费福利小电影 | 美女国产网站 | 国产精自产拍久久久久久蜜 | 一本大道久久久久精品嫩草 | 精东影业一区二区三区 | 久久久综合久久 | 国产精品久久久久久一区二区三区 | 色婷婷五 | 福利在线播放 | 久久99免费视频 | 亚洲精品人人 | 欧美淫 | 国产精品12区 | 无码人妻精品一区二区50 | 亚洲狼人社区 | 欧美一级少妇 | 黄污视频网站 | 超碰三级 | 国产免费不卡视频 | 日韩欧美一区二区三区在线观看 | 亚洲精品资源在线 | 一级特级毛片 |