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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线索二叉树(基于链表存储树结点)

發布時間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线索二叉树(基于链表存储树结点) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有以下場景

如果使用中序遍歷,那么得到的順序是:HDIBEAFCG,可以得知A的前驅結點為E,后繼結點為F。但是,這種關系的獲得是建立在完成遍歷后得到的。如果我們每次想得到某個節點的前驅或者后繼,都要先遍歷整棵樹,未免太過于麻煩了!我們為何不在生成該樹的時候,就直接將結點的前驅后后繼寫入結點的屬性中,提高在后續尋找前驅結點和后繼結點的效率?這就是線索二叉樹的由來。
首先,得先明確以下概念:

1.n個結點的二叉鏈表中含有n+1個空指針域。利用二叉鏈表中的空指針域,存放指向該結點在某種遍歷次序下的前驅和后繼結 占的指針(這種附加的指針稱為"線索"2.這種加上了線索的二叉鏈表稱為線索鏈表,相應的二叉樹稱為線索二叉(ThreadedBinaryTree)。根據線索性質的不同,線索二叉樹可分為前序線索二叉樹、中序線索二叉樹和后序線索二叉樹三種。 3.一個結點的前一個結點,稱為前驅結點 4.一個結點的后一個結點,稱為后繼結點 5.二叉樹線索化時,通常規定,若左子樹為空,令其左子節點=其前驅結點,若右子樹為空,令其右子結點==其后繼結點。 6.指向結點得前驅后者后繼指針,便稱為線索。 7.將二叉樹以某種次序遍歷使其變為線索二叉樹的過程成為線索化


圖中的虛線為線索

出現問題:


上面的雙向鏈表,與線索化之后的二叉樹相比,比如節點D與后繼節點I,在完成線索化之后,并沒有直接線索指針,而是存在父子節點的指針;節點A與節點F,在線索化完成之后,節點A并沒有直接指向后繼節點F的線索指針,而是通過父子節點遍歷可以找到最終的節點F,前驅節點也存在同樣的問題,正因為很多節點之間不存在直接的線索,所以我將此雙向鏈表稱做“特殊的雙向鏈表”,再使用過程中根據指針是線索指針還是子節點指針來分別處理,所以在每個節點需要標明當前的左右指針是線索指針還是子節點指針,這就需要修改節點的數據結構,增加標志位。

isLeftThread為false時,指向左孩子,為ture時指向前驅 isRightThread為false時,指向右孩子,為ture時指向后繼

添加后結點結構如下:

節點類:

//節點存儲結構 static class Node {String data; //數據域Node left; //左指針域Node right; //右指針域Node parent; //父節點的指針(為了后序線索化使用)boolean isLeftThread = false; //左指針域類型 false:指向子節點、true:前驅boolean isRightThread = false; //右指針域類型 false:指向子節點、true:后繼Node(String data) {this.data = data;} }

添加標志位后的二叉樹:

線索樹代碼:

/*** @Title: 二叉樹相關操作* @Description:* @Author: Uncle Ming* @Date:2017年1月6日 下午2:49:14* @Version V1.0*/ public class ThreadBinaryTree {private Node preNode; //線索化時記錄前一個節點//節點存儲結構static class Node {String data; //數據域Node left; //左指針域Node right; //右指針域boolean isLeftThread = false; //左指針域類型 false:指向子節點、true:前驅或后繼線索boolean isRightThread = false; //右指針域類型 false:指向子節點、true:前驅或后繼線索Node(String data) {this.data = data;}}/*** 通過數組構造一個二叉樹(完全二叉樹)* @param array* @param index* @return*/static Node createBinaryTree(String[] array, int index) {Node node = null;if(index < array.length) {node = new Node(array[index]);node.left = createBinaryTree(array, index * 2 + 1);node.right = createBinaryTree(array, index * 2 + 2);}return node;}/*** 中序線索化二叉樹* @param node 節點*/void inThreadOrder(Node node) {if(node == null) {return;}//處理左子樹inThreadOrder(node.left);//左指針為空,將左指針指向前驅節點if(node.left == null) {node.left = preNode;node.isLeftThread = true;}//前一個節點的后繼節點指向當前節點if(preNode != null && preNode.right == null) {preNode.right = node;preNode.isRightThread = true;}preNode = node;//處理右子樹inThreadOrder(node.right);}/*** 中序遍歷線索二叉樹,按照后繼方式遍歷(思路:找到最左子節點開始)* @param node*/void inThreadList(Node node) {//1、找中序遍歷方式開始的節點while(node != null && !node.isLeftThread) {node = node.left;}while(node != null) {System.out.print(node.data + ", ");//如果右指針是線索if(node.isRightThread) {node = node.right;} else { //如果右指針不是線索,找到右子樹開始的節點node = node.right;while(node != null && !node.isLeftThread) {node = node.left;}}}}/*** 中序遍歷線索二叉樹,按照前驅方式遍歷(思路:找到最右子節點開始倒序遍歷)* @param node*/void inPreThreadList(Node node) {//1、找最后一個節點while(node.right != null && !node.isRightThread) {node = node.right;}while(node != null) {System.out.print(node.data + ", ");//如果左指針是線索if(node.isLeftThread) {node = node.left;} else { //如果左指針不是線索,找到左子樹開始的節點node = node.left;while(node.right != null && !node.isRightThread) {node = node.right;}}}}/*** 前序線索化二叉樹* @param node*/void preThreadOrder(Node node) {if(node == null) {return;}//左指針為空,將左指針指向前驅節點if(node.left == null) {node.left = preNode;node.isLeftThread = true;}//前一個節點的后繼節點指向當前節點if(preNode != null && preNode.right == null) {preNode.right = node;preNode.isRightThread = true;}preNode = node;//處理左子樹if(!node.isLeftThread) {preThreadOrder(node.left);}//處理右子樹if(!node.isRightThread) {preThreadOrder(node.right);}}/*** 前序遍歷線索二叉樹(按照后繼線索遍歷)* @param node*/void preThreadList(Node node) {while(node != null) {while(!node.isLeftThread) {System.out.print(node.data + ", ");node = node.left;}System.out.print(node.data + ", ");node = node.right;}}public static void main(String[] args) {String[] array = {"A", "B", "C", "D", "E", "F", "G", "H"};Node root = createBinaryTree(array, 0);ThreadBinaryTree tree = new ThreadBinaryTree();tree.inThreadOrder(root);System.out.println("中序按后繼節點遍歷線索二叉樹結果:");tree.inThreadList(root);System.out.println("\n中序按后繼節點遍歷線索二叉樹結果:");tree.inPreThreadList(root);Node root2 = createBinaryTree(array, 0);ThreadBinaryTree tree2 = new ThreadBinaryTree();tree2.preThreadOrder(root2);tree2.preNode = null;System.out.println("\n前序按后繼節點遍歷線索二叉樹結果:");tree.preThreadList(root2);} }

加上頭結點

有時為了方便,模仿線性表的存儲結構為了便于遍歷線索二叉樹,我們為其添加一個頭結點,頭結點左孩子指向原二叉樹的根結點,右孩子指針指向中序遍歷的最后一個結點。同時,將第一個結點左孩子指針指向頭結點,最后一個結點的右孩子指針指向頭結點。這好比為二叉樹建立了一個雙向線索鏈表,既可以從第一個結點起順后繼進行遍歷,又可以從最后一個結點起順前驅進行遍歷。

小結

  • 線索化的實質就是將二叉鏈表中的空指針改為指向前驅節點或后繼節點的線索;
  • 線索化的過程就是修改二叉鏈表中空指針的過程,可以按照前序、中序、后序的方式進行遍歷,分別生成不同的線索二叉樹;
  • 有了線索二叉樹之后,我們再次遍歷時,就相當于操作一個雙向鏈表。
  • 使用場景:如果我們在使用二叉樹過程中經常需要遍歷二叉樹或者查找節點的前驅節點和后繼節點,可以考慮采用線索二叉樹存儲結構。
  • 本文轉載于

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的线索二叉树(基于链表存储树结点)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 国产精品无码永久免费不卡 | 99国产揄拍国产精品 | 日本一级三级三级三级 | 国产成人精品在线视频 | 深爱激情av | 这里只有精品在线观看 | 91天天干| 人人爽爽爽 | aa黄色片| 天天做夜夜爽 | 岛国av中文字幕 | 中国国产黄色片 | 婷婷激情久久 | 国产1区2区3区4区 | 久久99免费 | 九月婷婷丁香 | 伊人96| 激情文学8888| 亚洲av永久一区二区三区蜜桃 | 成年人免费黄色 | 性中国古装videossex | 日日夜夜免费精品 | 国产成人麻豆精品午夜在线 | 欧美三级不卡 | 精品无码久久久久久久久成人 | 久久激情五月 | 久久免费av| 男女av| 夜夜骑夜夜操 | 操久久| 久艹在线播放 | 天堂最新资源在线 | 国产精品s色| 西西人体44www大胆无码 | 伊人久综合| 超碰人人澡 | 性欧美日本 | 色永久| 午夜精品久久久久久久99老熟妇 | 91麻豆产精品久久久久久夏晴子 | 色伊人影院 | aa爱做片免费 | 视频一区二区在线 | 五月婷婷俺也去 | 国产免费看 | 麻豆91茄子在线观看 | 91综合网 | 欧美精品手机在线 | 老公吃小头头视频免费观看 | 给我看高清的视频在线观看 | 国产日韩在线免费观看 | 免费av网站在线播放 | 国产91精品一区二区 | 伊人天天操| 一边摸上面一边摸下面 | 美国美女黄色片 | www欧美色| 免费观看黄色网址 | 影音先锋成人网 | 日本美女交配 | 日本做爰三级床戏 | 91豆花视频 | 欧美日韩经典 | 成人免费视频播放 | 久久麻豆视频 | 在线观看av日韩 | 97影院| 校花被c到呻吟求饶 | 91视频论坛 | 亚洲成人免费观看 | 欧美日韩精 | 十八岁世界在线观看高清免费韩剧 | 黄在线免费观看 | 97超碰伊人| 人人干天天操 | 91香蕉视频官网 | 亚洲无码精品一区二区三区 | 国产在线播放91 | 国产一区中文 | 性chinese天美传媒麻 | 国产一区二区在线播放视频 | 久久夜色网 | 欧美黑人性猛交xxxx | 萌白酱一区二区 | av一区二| 亚洲欧美视频在线播放 | av在线官网 | 免费在线视频你懂的 | 国精品一区二区 | av免费在线不卡 | 国产精品久久中文字幕 | 青草青在线 | 一区二区三区在线观看av | 神马久久网站 | 美女撒尿无遮挡网站 | 粉嫩av蜜桃av蜜臀av | 老汉色老汉首页av亚洲 | 猛男被粗大男男1069 | 亚洲一区二区在线观看视频 |