Java プログラミング スキル - データ構造とアルゴリズム「スレッド バイナリ ツリー」

Java プログラミング スキル - データ構造とアルゴリズム「スレッド バイナリ ツリー」

[[388829]]

まず質問を見てみましょう

シーケンス{1,3,6,8,10,14}を二分木に構築します。次の図に示すように、n+1=7です。


問題分析:

  1. 上記の二分木を順番に走査すると、シーケンスは{8,3,10,1,14,6}になります。
  2. ただし、ノード 6、8、10、および 14 の左および右のポインタは完全には使用されていません。
  3. 各ノードの左と右のポインタを最大限に活用し、各ノードがその前面ノードと背面ノードを指すようにしたい場合はどうすればよいでしょうか。
  4. ソリューション - スレッドバイナリツリー

スレッドバイナリツリーの基本的な紹介

  1. n 個のノードのバイナリ リンク リストには、n+1 [式 2n-(n-1)=n+1] 個の null ポインター フィールドが含まれます。バイナリ リンク リスト内の空のポインタ フィールドは、特定のトラバーサル順序でノードの前ポイントと後ポイントへのポインタを格納するために使用されます (この追加のポインタは、手がかりと呼ばれます)。
  2. このスレッド付きのバイナリリンクリストはスレッドリンクリストと呼ばれ、対応するバイナリツリーはスレッドバイナリツリー (Threaded Binary Tree) と呼ばれます。ヒントの性質に応じて、ヒント付きバイナリツリーは、前順序ヒント付きバイナリツリー、中順序ヒント付きバイナリツリー、後順序ヒント付きバイナリツリーの 3 つのタイプに分けられます。
  3. ノードの前のノードは先行ノードと呼ばれます。
  4. ノードの後のノードは後続ノードと呼ばれます。

順序手がかり二分木図


順序通りの走査の結果は{8,3,10,1,14,6}です。

注: バイナリ ツリーがスレッド化された後、Node ノードの左と右の属性は次のようになります。

  1. left が指す値は左のサブツリー、または指し示す先行ノードです。たとえば、ノード ① の左は左のサブツリーを指し、ノード ⑩ の左は先行ノードを指します。
  2. right が指す右サブツリーは、後続ノードを指すこともあります。たとえば、ノード ① の右は右サブツリーを指し、ノード ⑩ の右は後続ノードを指します。

コード例

  1. パッケージ com.xie.tree.threadedbinarytree;
  2.  
  3. パブリッククラスThreadedBinaryTreeDemo {
  4. 公共 静的void main(String[] args) {
  5. // 順序付き手がかりバイナリツリーをテストする
  6. HeroNode ルート = 新しい HeroNode(1, "tom" );
  7. HeroNode node2 = 新しいHeroNode(3, "jack" );
  8. HeroNode node3 = 新しいHeroNode(6, "smith" );
  9. HeroNode node4 = 新しいHeroNode(8, "mary" );
  10. HeroNode node5 = 新しいHeroNode(10, "king" );
  11. HeroNode node6 = 新しいHeroNode(14, "dim" );
  12.  
  13. ルート.setLeft(ノード2);
  14. ルートを右に設定します(ノード3);
  15.  
  16. ノード4を左に設定します。
  17. ノード2を右に設定します(ノード5);
  18.  
  19. ノード3を左に設定します(ノード6);
  20.  
  21. スレッドバイナリツリー threadedBinaryTree = 新しい ThreadedBinaryTree();
  22. スレッドバイナリツリー。ルートを設定します。
  23. スレッドバイナリツリー。
  24.  
  25. //テスト: ノード10でテスト
  26. HeroNode= node5.getLeft();
  27. System.out.println ( "ノード10の前身ノードは:" + left );
  28. HeroNode= node5.getRight();
  29. System.out.println ( "ノード10の後継ノードは:" + right );
  30.  
  31. System.out.println ( "スレッドアプローチを使用してスレッドバイナリツリーをトラバースします" );
  32. スレッドバイナリツリー。スレッドバイナリツリーリスト();
  33.  
  34. /**
  35. * ノード 10 の前身ノードは、HeroNode{ no =3, name =jack}です。
  36. * ノード10の後継ノードは、HeroNode{ no =1, name =tom}です。
  37. * スレッド化されたアプローチを使用して、スレッド化されたバイナリツリーをトラバースします。
  38. * HeroNode{番号=8、名前=mary}
  39. * HeroNode{番号=3、名前=jack}
  40. * HeroNode{番号=10、名前=king}
  41. * HeroNode{番号=1、名前=tom}
  42. * HeroNode{ no =14, name =dim}
  43. * HeroNode{番号=6、名前=smith}
  44. */
  45.  
  46. }
  47. }
  48.  
  49. //スレッド関数を実装するバイナリツリー
  50. クラス ThreadedBinaryTree {
  51. プライベート HeroNode ルート;
  52. //スレッド化を実現するには、現在のノードの前のノードへのポインタを作成する必要があります
  53. //再帰的にスレッド化する場合、pre は常に前のノードを保持します
  54. プライベートHeroNode pre;
  55.  
  56. パブリックvoid setRoot(HeroNode ルート) {
  57. ルート
  58. }
  59.  
  60. /**
  61. * スレッド化されたバイナリツリーをトラバースするためのメソッド。
  62. */
  63. パブリックボイドスレッドバイナリツリーリスト() {
  64. //ルートから現在トラバースされているノードを格納する変数を定義します
  65. HeroNode ノード = ルート;
  66. while (ノード ​​!= null ) {
  67. // leftType==1 のノードを探すためにループします。最初に見つかったのはノード 8 です。
  68. // トラバーサルが進むにつれて、次の内容が変わります。leftType==1 の場合、スレッド処理後にノードが有効なノードであることを意味します。
  69. (node.getLeftType() == 0) の間 {
  70. ノード = node.getLeft();
  71. }
  72. //現在のノードを印刷する
  73. System.out.println (ノード) ;
  74. //現在のノードの右ポインタが後続ノードを指している場合は、出力を続けます
  75. (node.getRightType() == 1) の間 {
  76. //現在のノードの後継ノードを取得します
  77. ノード = node.getRight();
  78. System.out.println (ノード) ;
  79. }
  80. // 走査したノードを置き換える
  81. ノード = node.getRight();
  82. }
  83. }
  84.  
  85. /**
  86. * threadedNodes メソッドをオーバーロードする
  87. */
  88. パブリックボイドスレッドノード(){
  89. スレッドノード(ルート);
  90. }
  91.  
  92. /**
  93. * バイナリツリーをスレッド化するメソッドを書く
  94. *
  95. * @param node 現在スレッド化する必要があるノード
  96. */
  97. パブリックvoid threadedNodes(HeroNode ノード) {
  98. if (ノード == null ) {
  99. 戻る;
  100. }
  101.  
  102. //まず左のサブツリーをスレッドする
  103. スレッド化されたノード(node.getLeft());
  104. //現在のノードをキューする [難しい]
  105.  
  106. //現在のノードの前身ノードを処理する
  107. //8 ノード、8ノードとして理解します。left = null  
  108. (node.getLeft() == nullの場合){
  109. //現在のノードの左ポインタを前のノードを指すようにします
  110. ノードを左に設定します(pre);
  111. //現在のノードの左ポインタ型を変更する
  112. ノードを左タイプに設定します(1);
  113. }
  114.  
  115. //後続ノードを処理する
  116. pre != null && pre.getRight() == null の場合{
  117. //先行ノードの右ポインタを現在のノードを指すようにします
  118. ノードを右に設定します。
  119. //先行ノードの右ポインタ型を変更する
  120. プレセットRightType(1);
  121. }
  122. //各ノードを処理した後、現在のノードを次のノードの前身ノードにします
  123. pre = ノード;
  124.  
  125. //右のサブツリーを再スレッドする
  126. スレッド化されたノード(node.getRight());
  127. }
  128.  
  129. }
  130.  
  131. //HeroNodeノードを作成
  132. クラスHeroNode {
  133. 静的 プリカウント = 0;
  134. 静的  int インフォックスカウント = 0;
  135. 静的 投稿= 0;
  136.  
  137. プライベートint  いいえ;
  138. プライベート文字列;
  139. プライベートHeroNodeが残りました;
  140. プライベートHeroNode;
  141.  
  142. //0 は左のサブツリーを指し、1 は前のノードを指していることを意味します
  143. プライベートint leftType;
  144. //0は右のサブツリーを指し、1は後続ノードを指していることを意味します
  145. プライベートint rightType;
  146.  
  147. パブリックHeroNode( int  いいえ、文字列){
  148. this.no =いいえ;
  149. this.name =名前;
  150. }
  151.  
  152. 公共 整数getNo() {
  153. 戻る いいえ;
  154. }
  155.  
  156. パブリックボイドsetNo( int  いいえ) {
  157. this.no =いいえ;
  158. }
  159.  
  160. パブリック文字列getName() {
  161. 戻る 名前;
  162. }
  163.  
  164. パブリックvoid setName(文字列) {
  165. this.name =名前;
  166. }
  167.  
  168. パブリックHeroNode getLeft() {
  169. 戻る ;
  170. }
  171.  
  172. パブリックvoid setLeft(HeroNode left ) {
  173. this.left =;
  174. }
  175.  
  176. パブリックHeroNode getRight() {
  177. 戻る ;
  178. }
  179.  
  180. パブリックvoid setRight(HeroNode) {
  181. this.right =;
  182. }
  183.  
  184. 公共  int getLeftType() {
  185. leftTypeを返します
  186. }
  187.  
  188. パブリックvoid setLeftType( int leftType) {
  189. this.leftType = leftType;
  190. }
  191.  
  192. 公共  int getRightType() {
  193. rightTypeを返します
  194. }
  195.  
  196. パブリックvoid setRightType( int rightType ) {
  197. this.rightType = 右タイプ;
  198. }
  199.  
  200. @オーバーライド
  201. パブリック文字列toString() {
  202. 戻る  「ヒーローノード{" +
  203. 「いいえ=」 +いいえ+
  204. ", 名前=" +名前+
  205. '}' ;
  206. }
  207.  
  208. // 事前順序トラバーサル
  209. パブリックボイドpreOrder() {
  210. System.out.println (これ) ;
  211. // 左のサブツリーを前順序で再帰的に走査する
  212. if ( this.left != null ) {
  213. this.left.preOrder ();
  214. }
  215.  
  216. // 右のサブツリーを前順序で再帰的に走査する
  217. if ( this.right != null ) {
  218. this.right .preOrder();
  219. }
  220. }
  221.  
  222. // 順序通りの走査
  223. パブリックvoid infixOrder() {
  224. //左のサブツリーを順番に再帰的に走査する
  225. if ( this.left != null ) {
  226. this.left .infixOrder();
  227. }
  228. System.out.println (これ) ;
  229. //右のサブツリーを順番に再帰的に走査する
  230. if ( this.right != null ) {
  231. this.right .infixOrder();
  232. }
  233. }
  234.  
  235. //後順走査
  236. パブリックボイドpostOrder() {
  237. // 左のサブツリーを後順に再帰的に走査する
  238. if ( this.left != null ) {
  239. this.left .postOrder();
  240. }
  241. // 右のサブツリーを後順で再帰的に走査する
  242. if ( this.right != null ) {
  243. this.right .postOrder();
  244. }
  245. System.out.println (これ) ;
  246. }
  247.  
  248. // ノードを再帰的に削除する
  249. //1. 削除するノードがリーフノードの場合は、そのノードを削除します。
  250. //2. 削除されたノードが非リーフノードの場合は、ツリーを削除します。
  251. パブリックvoid delNo( int  いいえ) {
  252. /**
  253. * 1. バイナリ ツリーは一方向であるため、現在のノードの子ノードが削除する必要があるノードであるかどうかを判断できますが、現在のノードが削除する必要があるノードであるかどうかを判断することはできません。
  254. * 2. 現在のノードの左の子が空でなく、左の子が削除対象のノードである場合は、 this.left = null ; を設定して戻ります (再帰を終了)。
  255. * 3. 現在のノードの右の子が空でなく、右の子が削除対象のノードである場合は、 this.right = null ; を設定して戻ります (再帰を終了)。
  256. * 4. 手順 2 と 3 でノードが削除されない場合、左のサブツリーに対して再帰的な削除が実行されます。
  257. * 5. 手順 4 でノードが削除されなかった場合は、右側のサブツリーに対して再帰的な削除を実行する必要があります。
  258. */
  259. if ( this.left != null && this.left . no == no ) {
  260. this.left = null ;
  261. 戻る;
  262. }
  263.  
  264. this.right != null && this.right . no == no場合{
  265. this.right = null ;
  266. 戻る;
  267. }
  268.  
  269. if ( this.left != null ) {
  270. this.left.delNo (いいえ) ;
  271. }
  272.  
  273. if ( this.right != null ) {
  274. this.right .delNo(いいえ);
  275. }
  276.  
  277. }
  278.  
  279. // 先行順序トラバーサル検索
  280. パブリックHeroNode preOrderSearch( int  いいえ) {
  281.  
  282. HeroNode res = null ;
  283.  
  284. preCount++; //実際の比較を実行するには、 this.no == no の判定の前にこれを配置する必要があります。
  285. //見つかった場合は返す
  286. if ( this.no == no ) {
  287. これを返します
  288. }
  289. //見つからない場合は、左のサブツリーを再帰的に検索して先行順序を検索します
  290. if ( this.left != null ) {
  291. res = this.left.preOrderSearch ( no );
  292. }
  293. // res の場合! = nullは直接返されます
  294. (res != null )の場合{
  295. resを返します
  296. }
  297. //左のサブツリーが見つからない場合は、右のサブツリーに対して事前順序検索を実行します
  298. if ( this.right != null ) {
  299. res = this.right.preOrderSearch ( no );
  300. }
  301. // 見つかった場合は返す
  302. (res != null )の場合{
  303. resを返します
  304. }
  305. resを返します
  306. }
  307.  
  308. // 順序通りのトラバーサル検索
  309. パブリックHeroNode infixOrderSearch( int  いいえ) {
  310.  
  311. HeroNode res = null ;
  312. if ( this.left != null ) {
  313. res = this.left.infixOrderSearch (いいえ);
  314. }
  315. (res != null )の場合{
  316. resを返します
  317. }
  318. infoxCount++; //実際の比較を実行するには、 this.no == no の判定の前にこれを配置する必要があります。
  319. if ( this.no == no ) {
  320. これを返します
  321. }
  322. if ( this.right != null ) {
  323. res = this.right.infixOrderSearch (いいえ);
  324. }
  325. (res != null )の場合{
  326. resを返します
  327. }
  328. resを返します
  329. }
  330.  
  331. // 後順トラバーサル検索
  332. パブリックHeroNode postOrderSearch( int  いいえ) {
  333.  
  334. HeroNode res = null ;
  335. if ( this.left != null ) {
  336. res = this.left.postOrderSearch ( no );
  337. }
  338. (res != null )の場合{
  339. resを返します
  340. }
  341.  
  342. if ( this.right != null ) {
  343. res = this.right.postOrderSearch (いいえ);
  344. }
  345. (res != null )の場合{
  346. resを返します
  347. }
  348. postCount++; //実際の比較を実行するには、 this.no == no の判定の前にこれを配置する必要があります
  349. if ( this.no == no ) {
  350. これを返します
  351. }
  352. resを返します
  353. }
  354. }

【編集者のおすすめ】

  1. 妹に Java 16 の新機能について話しましたが、とても素晴らしいそうです!
  2. IT プロジェクトが多すぎて管理が難しくなっていませんか?いいえ!あなたはまだこの7つのコツを学んでいないからです
  3. Pythonを5年間学んできましたが、これらのウェブサイトをもっと早く知らなかったことを後悔しています。ぜひ一緒に見に来てください。
  4. Java はすでに 16 まで達しているのに、なぜまだ 8 が使われているのでしょうか? どんどん悪化しているのでしょうか?
  5. すごいですね! Windows 10 のこれらのブラックテクノロジー機能を使用したことがありますか?

<<:  世界で最も難しい「砂の彫刻」ゲームがAIによって解読された

>>:  大きな AI 問題の解決: AI 操作のエネルギー消費を削減するにはどうすればよいでしょうか?

ブログ    
ブログ    
ブログ    

推薦する

ハリー・シャムが清華大学の記録を破り、ビデオを通じて任命された史上初の教授となり、説明可能なAIを訴える

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

斉燕傑:Sina Weibo のパーソナライズされたプッシュにおける機械学習の応用

[51CTO.comより引用] Sina Weiboは情報交換プラットフォームであるだけでなく、メデ...

アルゴリズムの改善とハードウェアの反復、どちらがより収益性が高いでしょうか? MITの最新の研究結果がこの答えを提供している

コンピューターが登場する前には、アルゴリズムがありました。コンピュータの誕生により、コンピュータの強...

人工知能、遺伝子編集、ノーベル賞の画期的な進歩により、80歳でも40歳に見えるようになる

年齢を重ねるにつれ、老化を遅らせて若さを取り戻すことが多くの人の夢となります。 クレオパトラにしろ、...

世界人工知能会議の最高栄誉である2020年SAIL賞のトップ30プロジェクトが発表されました

世界人工知能会議の最高賞であるSAIL賞(スーパーAIリーダー)は、「卓越性を追求し、未来をリードす...

Web 2.0 のソーシャル関連性ランキング アルゴリズムの探究

FriendFeed は最近検索機能を開始しましたが、Facebook もすぐに追随すると思います。...

国内メディアが大々的に報じた「世界初のAI地震監視システム」は的外れ

[[387555]]この記事はLeiphone.comから転載したものです。転載する場合は、Leip...

顔認識訪問者システムの利点は何ですか?

[[373764]]顔認識訪問者システムの利点は何ですか?以前は、訪問者の管理に手書きの登録が使用...

ロンドンの顔認識で誤った人物が逮捕される:合理的な使用が鍵

顔認識の応用範囲は、アクセス制御やデバイスログインから空港や公共エリアの監視まで、非常に広範囲にわた...

ユニバーサルで説明可能なAIコンピューティングハードウェア設計は、EDAにおける次の革命的な技術となるでしょう。

この記事はLeiphone.comから転載したものです。転載する場合は、Leiphone.com公式...

任澤平:「新インフラ」は時代の痕跡を刻む

【51CTO.comオリジナル記事】今年、我が国では間違いなく新しいインフラがホットな話題です。 2...

Facebookは人々の生活を一人称で分析する新しいAIシステムを開発中

Facebookは、独自のARグラスを開発するためにRay-Banと提携するなど、拡張現実技術に多大...

...

百度、中国企業のインテリジェントアップグレードプロセスを加速させる新型PaddlePaddleスマートマシンを発売

クラウドとインテリジェンスの統合は、中国企業が AI アプリケーションの実装の「最後の 1 マイル」...

Google は、99% のプログラマーに勝る AutoML を Kaggle プラットフォームに統合しました。

今後、Kaggle のコンペティションに参加する際には、AutoML を直接送信して、参加する AI...