演算法與資料結構之美 二叉樹

2021-09-25 20:10:49 字數 4335 閱讀 4034

二叉查詢樹(binary search tree)

關於樹,有幾個比較相似的概念:高度(height)深度(depth)層(level)

定義:

二叉樹,每個節點有兩個叉,分別是左子節點和右子節點;

滿二叉樹,就是除了葉子節點之外,其餘的所有節點都有左右兩個子節點;

完全二叉樹,為什麼最後一層的葉子節點靠左排列的叫完全二叉樹呢?為啥靠右排列的就不能叫完全二叉樹呢?

思考一下如何來儲存二叉樹呢?

1、基於指標或者引用的二叉鏈式儲存法

簡單、直觀的鏈式儲存法,每個節點有三個字段,其中乙個儲存資料,另外兩個是指向左右子節點的指標,只要抓住根節點,就可以通過左右子節點的指標,把整棵樹都串聯起來,如下圖所示:

2、基於陣列的順序儲存法

根節點儲存在下標i=1的位置,那麼左子節點儲存在下標2i=2的位置,右子節點儲存在2i+1=3的位置,依次類推:b節點的左子節點儲存在2i= 22 =4的位置,右子節點儲存在2*i+1=5的位置;

總結:節點x儲存在陣列中下標為i的位置,下標為2i的位置儲存的就是左子節點,下標為2i+1儲存的就是右子節點;

所以如果某棵樹是完全二叉樹,採用順序陣列儲存的方式無疑是最省記憶體的,因為不需要額外的儲存空間來儲存左右子節點的指標;所以完全二樹最後一層的葉子節點都要靠左排列,是因為不想造成額外的記憶體資源浪費;

前、中、後序遍歷就是乙個遞迴的過程,遞推公式如下:

前序遍歷的遞推公式

preorder =

print

(root)

->

print

(root.left)

->

print

(root.right)

中序遍歷的遞推公式

inorder =

print

(root.left)

->

print

(root)

->

print

(root.right)

後序遍歷的遞推公式

postorder =

print

(root.left)

->print-

>

(root.right)

->

print

(root)

class

treenode

}//遞迴實現

//前序遍歷

public

static

void

preorder

(treenode root)

treenode righttree = root.right;

if(righttree!=null)

}//非遞迴實現

public

static

void

preorder

(treenode root)

else}}

//中序遍歷

//遞迴實現

public

static

void

inorder

(treenode root)

system.out.

println

(root.value)

; treenode righttree = root.right;

if(righttree != tree)

}//非遞迴實現

public

static

void

inorder

(treenode root)

else}}

//後序遍歷

//遞迴實現

public

static

void

postorder

(treenode root)

}//非遞迴實現

public

static

void

postorder

(treenode root)if(

!stack.

isempty()

&&stack2.

peek()

==left)

while

(!stack.

isempty()

&&stack2.

peek()

==right)}}

//乙個棧實現後序遍歷

public

void

postorder

(treenode)}}

system.out.

println()

;}

對於非遞迴實現的遍歷,建議自己畫個樹,順著**走一遍,這樣理解起來會簡單一些,千萬不要死記硬背**的實現,因為睡一覺啥都記不起來了!時間複雜度二叉樹的遍歷與節點個數n成正比,所以二叉樹遍歷的時間複雜度是o(n);

二叉查詢樹的要求,在樹中的任意一節點,其左子樹的每個節點的值,都小於該節點的值,其右子樹節點的值都大於該節點的值;

在二叉查詢樹中查詢乙個節點,先取根節點,如果要查詢的資料就是根節點,直接返回;如果要查詢的資料比根節點的值要小,那就在左子樹中遞迴查詢;如果要查詢的資料比根節點的值要大,那就在右子樹中遞迴查詢;

**如下

public

class

binarysearchtree}}

public

static

class

node

}}

從根節點開始依次進行比較:

public

void

insert

(int data)

node p = tree;

while

(p!=null)

p = p.right;

}else

p = p.left;}}

}

根據要刪除的節點個數不同,二叉查詢樹的刪除操作分為三種情況來考慮:

public

void

delete

(int data)

if(p==null)

return

;//沒有找到

//要刪除的有兩個子節點

if(p.left!=null&&p.right!=null)

p.data = minp.data;

//將minp的資料替換到p中

p = minp;

pp = minpp;

}//刪除節點是葉子節點或者僅有乙個子節點

node child;

if(p.left!=null) child =p.left;

else

if(p.right!=null) child = p.right;

else child = null;

if(pp==null) tree = child;

else

if(pp.left==p) pp.left = child;

else child = null;

}public node findmin()

return p;

}public node findmax()

return p;

}

中序遍歷二叉查詢樹,可以輸出有序的資料序列,時間複雜度是o(n);

不管是插入、查詢、刪除操作,時間複雜度都是和樹的高度成正比的,那麼如何求一棵包含n個節點的完全二叉樹的高度?

對於包含n個節點的完全二叉樹中,第一層包含1個節點,第二層包含兩個節點,第三層包含4個節點,依次類推,第k層包含的節點個數就是2^(k-1);

那麼n滿足的關係式如下:

演算法與資料結構 二叉樹

二叉樹 binary tree 二分樹 二元樹 二叉樹的遞迴定義 或是空樹,或是一棵由乙個根結點和左右子樹組成的樹,且左右子樹也是二叉樹。分枝結點 除葉結點以外的結點。二叉樹的性質 最多 2 h 1 個結點 n2 n0 1 滿二叉樹 所有分枝結點都存在左右子樹,且葉結點都在同一層。完全二叉樹 除最後...

資料結構與演算法 二叉樹

1.普通二叉樹 treenode package math public class treenode public void setdata int data public treenode getlchild public void setlchild treenode lchild publi...

資料結構與演算法 二叉樹

二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作 左子樹 left subtree 和 右子樹 right subtree 性質1 在二叉樹的第i層上至多有2 i 1 個結點 i 0 性質2 深度為k的二叉樹至多有2 k 1個結點 k 0 性質3 對於任意一棵二叉樹,如果其葉結點數為n0,而度...