樹的線索化

2021-09-25 05:06:00 字數 4352 閱讀 5430

先看乙個問題

將數列 構建成一顆二叉樹. n+1=7

當我們對上面的二叉樹進行中序遍歷時,數列為

但是 6, 8, 10, 14 這幾個節點的 左右指標,並沒有完全的利用上.

如果我們希望充分的利用 各個節點的左右指標, 讓各個節點可以指向自己的前後節點,怎麼辦?

解決方案-線索二叉樹

n 個結點的二叉鍊錶中含有 n+1 【公式 2n-(n-1)=n+1】 個空指標域。利用二叉鍊錶中的空指標域,存放指向該結點在某種遍歷次序下的前驅和後繼結點的指標(這種附加的指標稱為"線索")

這種加上了線索的二叉鍊錶稱為線索鍊錶,相應的二叉樹稱為線索二叉樹(threaded binarytree)。根據線索性質的不同,線索二叉樹可分為前序線索二叉樹、中序線索二叉樹和後序線索二叉樹三種

乙個結點的前乙個結點,稱為前驅結點

乙個結點的後乙個結點,稱為後繼結點

說明: 當線索化二叉樹後,node 節點的 屬性 left 和 right ,有如下情況:

left 指向的是左子樹,也可能是指向的前驅節點. 比如 ① 節點 left 指向的左子樹, 而 ⑩ 節點的 left 指向的就是前驅節點.

right 指向的是右子樹,也可能是指向後繼節點,比如 ① 節點 right 指向的是右子樹,而⑩ 節點的 right 指向的是後繼節點.

**實現:

package com.xxd.tree.threadedtree;

public class threadedbinarytreedemo

}class threadedbinarytree

// 遍歷線索化二叉樹的方法

public void threadedlist()

// 列印這個節點

system.out.println(node);

// 如果當前結點的右指標指向的是後繼結點,就一直輸出 ( 後繼節點 其實跟 右子樹 是有區別的哦)

while (node.getrighttype() == 1)

node = node.getright();

} }// 過載一把threadednodes方法

public void threadednodes()

// 編寫對二叉樹進行中序線索化的方法

public void threadednodes(heronode node)

// (一)先線索化左子樹

threadednodes(node.getleft());

// (二)線索化當前結點[有難度]

// 處理當前節點的前驅節點

if (node.getleft() == null)

// 處理後繼節點

if (pre != null && pre.getright() == null)

pre = node;

threadednodes(node.getright());

} // 刪除結點

public void delnode(int no) else

} else

} // 前序遍歷

public void preorder() else

} // 中序遍歷

public void infixorder() else

} // 後序遍歷

public void postorder() else

} // 前序遍歷

public heronode preordersearch(int no) else

} // 中序遍歷

public heronode infixordersearch(int no) else

} // 後序遍歷

public heronode postordersearch(int no) else }}

//先建立heronode 結點

class heronode

public void setlefttype(int lefttype)

public int getrighttype()

public void setrighttype(int righttype)

public heronode(int no, string name)

public int getno()

public void setno(int no)

public string getname()

public void setname(string name)

public heronode getleft()

public void setleft(heronode left)

public heronode getright()

public void setright(heronode right)

@override

public string tostring()

// 遞迴刪除結點

// 1.如果刪除的節點是葉子節點,則刪除該節點

// 2.如果刪除的節點是非葉子節點,則刪除該子樹

public void delnode(int no)

// 3.如果當前結點的右子結點不為空,並且右子結點 就是要刪除結點,就將this.right= null ;並且就返回(結束遞迴刪除)

if (this.right != null && this.right.no == no)

// 4.我們就需要向左子樹進行遞迴刪除

if (this.left != null)

// 5.則應當向右子樹進行遞迴刪除

if (this.right != null)

} // 編寫前序遍歷的方法

public void preorder()

// 遞迴向右子樹前序遍歷

if (this.right != null)

} // 中序遍歷

public void infixorder()

// 輸出父結點

system.out.println(this);

// 遞迴向右子樹中序遍歷

if (this.right != null)

} // 後序遍歷

public void postorder()

if (this.right != null)

system.out.println(this);

} // 前序遍歷查詢

public heronode preordersearch(int no)

// 1.則判斷當前結點的左子節點是否為空,如果不為空,則遞迴前序查詢

// 2.如果左遞迴前序查詢,找到結點,則返回

heronode resnode = null;

if (this.left != null)

if (resnode != null)

// 1.左遞迴前序查詢,找到結點,則返回,否繼續判斷,

// 2.當前的結點的右子節點是否為空,如果不空,則繼續向右遞迴前序查詢

if (this.right != null)

return resnode;

} // 中序遍歷查詢

public heronode infixordersearch(int no)

if (resnode != null)

system.out.println("進入中序查詢");

// 如果找到,則返回,如果沒有找到,就和當前結點比較,如果是則返回當前結點

if (this.no == no)

// 否則繼續進行右遞迴的中序查詢

if (this.right != null)

return resnode;

} // 後序遍歷查詢

public heronode postordersearch(int no)

if (resnode != null)

// 如果左子樹沒有找到,則向右子樹遞迴進行後序遍歷查詢

if (this.right != null)

if (resnode != null)

system.out.println("進入後序查詢");

// 如果左右子樹都沒有找到,就比較當前結點是不是

if (this.no == no)

return resnode;

}}

線索化的目的 就是加快遍歷速度

線索二叉樹的線索化演算法

在嚴蔚敏的 資料結構 一書中,所使用的 存在一些小問題。原版 就不附上了,主要問題是 1.inthreading函式的引數,應該攜帶pre,這應該是比較嚴重的問題。如果沒有攜帶pre,則對pre的修改只是在呼叫的函式中的區域性變數的值的修改,沒有影響到原來的pre的值。2.在條件語句中,將命中概率高...

線索二叉樹的線索化和析構

前段時間學習的二叉樹的相關操作,現在又開始學習線索二叉樹的相關操作,發現網的一些 有問題,所以寫了這篇部落格與大家分享,以下這些 都是我親自編寫以及除錯執行過,有什麼錯的還請大家指出。線索二叉樹結點的定義如下 template class t class threadnode threadnode ...

線索二叉樹的定義 結構以及線索化

1 線索二叉樹的基本概念 在二叉樹的每個結點中增加兩個指標域,用於存放遍歷二叉樹時得到的直接前驅和直接後繼的資訊。2 線索二叉樹的結點構造 ltag 0時,表示lchild指向結點的左孩子,lchild是乙個指標 結點有左孩子 ltag 1時,表示lchild指向結點的直接前驅,lchild是乙個線...