生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法--重建二叉树
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
二叉樹(shù)
- 樹(shù)在實(shí)際編程中經(jīng)常遇到地一種數(shù)據(jù)結(jié)構(gòu)。上一篇中我們解釋了二叉樹(shù)及其原理,從中可以知道,樹(shù)地操作會(huì)涉及到很多指針地操作,我們一般遇到地樹(shù)相關(guān)地問(wèn)題差不多都是二叉樹(shù)。二叉樹(shù)最重要地莫過(guò)于遍歷,即按照某一順序訪問(wèn)樹(shù)中所有節(jié)點(diǎn),通常有如下幾種遍歷方式:
- 前序遍歷:先根節(jié)點(diǎn),左節(jié)點(diǎn),右節(jié)點(diǎn)。用以上順序來(lái)訪問(wèn)
- 中序遍歷:先左節(jié)點(diǎn),中節(jié)點(diǎn),右節(jié)點(diǎn)
- 后續(xù)遍歷:先左節(jié)點(diǎn),右節(jié)點(diǎn),中節(jié)點(diǎn)
- 以上三種遍歷都有遞歸和循環(huán)兩種不同地實(shí)現(xiàn)方式,每一種遍歷地遞歸實(shí)現(xiàn)都比循環(huán)實(shí)現(xiàn)要簡(jiǎn)單。在上一節(jié)中已經(jīng)給出了三種遞歸遍歷地實(shí)現(xiàn)方式。
- 二叉樹(shù)還有很多特例,二叉搜索樹(shù)左子樹(shù)中節(jié)點(diǎn)總數(shù)小于或者等于根節(jié)點(diǎn)。右子樹(shù)地節(jié)點(diǎn)總數(shù)大于等于根節(jié)點(diǎn)。
- 二叉樹(shù)特例還包括堆和紅黑樹(shù)。堆分為最大堆和最小堆。
- 一下我們利用二叉樹(shù)地三種遍歷方式地特性來(lái)解決如下算法問(wèn)題:
重建二叉樹(shù)
- 題目:輸入某個(gè)二叉樹(shù)前序遍歷,中序遍歷地結(jié)果,請(qǐng)重建該二叉樹(shù)。我們假設(shè)駛?cè)氲厍靶虮闅v,中序遍歷不包含重復(fù)數(shù)字。例如:前序(1,2,4,7,3,5,6,8),中序遍歷(4,7,2,1,5,3,8,6),如下圖
分析
- 二叉樹(shù)前序遍歷中,第一個(gè)數(shù)字總數(shù)樹(shù)地根節(jié)點(diǎn)。
- 中序遍歷中,根節(jié)點(diǎn)在序列中間。左子樹(shù)在根節(jié)點(diǎn)左邊,右子樹(shù)在根節(jié)點(diǎn)右邊
- 我們通過(guò)前序遍歷找到根節(jié)點(diǎn)
- 在中序遍歷中確認(rèn)跟節(jié)點(diǎn)的位置后得到左右子樹(shù)的長(zhǎng)度
- 接著將左子樹(shù),右子樹(shù)分別執(zhí)行以上流程(遞歸)
- 如下圖,在二叉樹(shù)的前序遍歷和中序遍歷的序列中確定根節(jié)點(diǎn)的值,左子樹(shù)的值和右子樹(shù)的值
實(shí)現(xiàn)
- 以上對(duì)二叉樹(shù)節(jié)點(diǎn)地定義:
public class BinaryNode implements Comparable {private Object element
;private BinaryNode left
;private BinaryNode right
;private int height
;private int count
;public BinaryNode(Object element
, BinaryNode left
, BinaryNode right
) {this.element
= element
;this.left
= left
;this.right
= right
;this.count
= 1;this.height
= 0;}public int getHeight() {return height
;}public void setHeight(int height
) {this.height
= height
;}public Object
getElement() {return element
;}public void setElement(Object element
) {this.element
= element
;}public BinaryNode
getLeft() {return left
;}public void setLeft(BinaryNode left
) {this.left
= left
;}public BinaryNode
getRight() {return right
;}public void setRight(BinaryNode right
) {this.right
= right
;}public int getCount() {return count
;}public void setCount(int count
) {this.count
= count
;}@Overridepublic int compareTo(Object o
) {if (o
== null
) {return 1;}int flag
;if (o
instanceof Integer) {int myElement
= (int) this.element
- (int) o
;flag
= myElement
> 0 ? 1 : myElement
== 0 ? 0 : -1;} else {flag
= this.element
.toString().compareTo(o
.toString());}if (flag
== 0) {return 0;} else if (flag
> 0) {return 1;} else {return -1;}}
}
- 重構(gòu)二叉樹(shù)實(shí)現(xiàn)
package com
.ljm
.resource
.math
.binary
;
public class RebuildBinary {public static BinaryNode
construct(int[] preOrder
, int[] inOrder
){if(preOrder
== null
|| inOrder
== null
|| preOrder
.length
!= inOrder
.length
|| preOrder
.length
<= 0){System
.out
.println("Invalid input");return null
;}return constructCore(preOrder
, inOrder
, 0, preOrder
.length
-1, 0, inOrder
.length
-1);}public static BinaryNode
constructCore(int[] preOrder
, int[] inOrder
,int preStart
, int preEnd
,int inStart
, int inEnd
){int rootValue
= preOrder
[preStart
];BinaryNode rootNode
= new BinaryNode(rootValue
, null
, null
);if(preStart
== preEnd
){if(inStart
== inEnd
&& preOrder
[preStart
] == inOrder
[inStart
]){return rootNode
;}else {System
.out
.println("Invalid input");return null
;}}int rootInOrderIndex
= inStart
;while (rootInOrderIndex
<= inEnd
&& inOrder
[rootInOrderIndex
] != rootValue
){rootInOrderIndex
++;}if(rootInOrderIndex
== inEnd
&& inOrder
[rootInOrderIndex
] != rootValue
){System
.out
.println("Invalid input");return null
;}int leftLength
= rootInOrderIndex
- inStart
;if(leftLength
> 0){int leftInOrderStart
= inStart
;int leftInOrderEnd
= inStart
+ leftLength
- 1;int leftPreOrderStart
= preStart
+ 1;int leftPreOrderEnd
= preStart
+ leftLength
;rootNode
.setLeft(constructCore(preOrder
, inOrder
, leftPreOrderStart
, leftPreOrderEnd
, leftInOrderStart
, leftInOrderEnd
));}if(leftLength
< preEnd
- preStart
){int rightInOrderStart
= rootInOrderIndex
+ 1;int rightInOrderEnd
= inEnd
;int rightPreOrderStart
= preStart
+ 1 + leftLength
;int rightPreOrderEnd
= preEnd
;rootNode
.setRight(constructCore(preOrder
, inOrder
, rightPreOrderStart
, rightPreOrderEnd
, rightInOrderStart
, rightInOrderEnd
));}return rootNode
;}public static void main(String
[] args
) {int preOrder
[] = {1,2,4,7,3,5,6,8};int inOrder
[] = {4,7,2,1,5,3,8,6};BinaryNode binaryNode
= construct(preOrder
, inOrder
);PostfixExTOTreeEx
.printMiddleFirstTree(binaryNode
);}
}
- 以上我們?cè)诤瘮?shù)constructCore中,我們先根據(jù)前序遍歷序列地第一個(gè)數(shù)字,創(chuàng)建根節(jié)點(diǎn)。
- 接下來(lái)在中序遍歷中找到根節(jié)點(diǎn)位置
- 這樣就能確定左右子樹(shù)地?cái)?shù)量
- 在前序遍歷和中序遍歷地序列中劃分左右子樹(shù)節(jié)點(diǎn)后,
- 將左右子樹(shù)遞歸調(diào)用函數(shù)constructCore,分別構(gòu)建左右子樹(shù)。得到最終地樹(shù)
上一篇:數(shù)據(jù)結(jié)構(gòu)與算法–二叉樹(shù)實(shí)現(xiàn)原理
下一篇:數(shù)據(jù)結(jié)構(gòu)與算法–二叉查找樹(shù)實(shí)現(xiàn)原理
總結(jié)
以上是生活随笔為你收集整理的数据结构与算法--重建二叉树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。