面試過程中經常會問到二叉樹相關的問題,下面使用Go整理下二叉樹相關問題的代碼實現
樹的定義
//define the data struct
type BinaryTree struct {
pLeft *BinaryTree //The Left Branch
pRight *BinaryTree //The Right Branch
value interface{} //Store The Value Of Tree Node
}
樹節點的創建以及添加左右子樹節點
//create the BinaryTree node
func NewBinaryTree(value interface{}) *BinaryTree {
return &BinaryTree{nil, nil, value}
}
//Add left BinaryTree node
func (pSelf *BinaryTree) AddLeft(pBinaryTree *BinaryTree) {
pSelf.pLeft = pBinaryTree
}
//Add right BinaryTree node
func (pSelf *BinaryTree) AddRight(pBinaryTree *BinaryTree) {
pSelf.pRight = pBinaryTree
}
//Get Left Node
func (pSelf *BinaryTree) GetLeft() *BinaryTree{
return pSelf.pLeft
}
//Get Right Node
func (pSelf *BinaryTree) GetRight() *BinaryTree{
return pSelf.pRight
}
查找N個節點的公共父節點
對於這類問題可以藉助一個int變量標記一個節點的子樹爲目標節點的數量,當數量達標時將節點加入結果集中即可
//find common parent node
func FindCommonParant(pRoot *BinaryTree, pNodes []*BinaryTree) (int, []*BinaryTree) {
if nil == pRoot || len(pNodes) <= 0 {
return 0, nil
}
iLeftRet, leftnodes := FindCommonParant(pRoot.pLeft, pNodes)
iRightRet, rightnodes := FindCommonParant(pRoot.pRight, pNodes)
var result []*BinaryTree
iFlag := iLeftRet + iRightRet
if len(pNodes) == iFlag {
result = append(result, leftnodes...)
result = append(result, rightnodes...)
result = append(result, pRoot)
} else {
for i := 0; i < len(pNodes); i++ {
if pRoot == pNodes[i] {
iFlag++ //current node as the target node
break
}
}
}
return iFlag, result[:]
}
二叉樹的遍歷
二叉樹節點爲ANY類型,需實現打印接口
//二叉樹節點實現接口
type Bter interface {
Print() //節點的打印
}
//PreOrder traversal binary tree
func PreTraversal(pRoot *BinaryTree) {
if nil != pRoot {
if v, ok := pRoot.Value.(Bter); ok {
v.Print()
}
PreTraversal(pRoot.pLeft)
PreTraversal(pRoot.pRight)
}
}
//非遞歸先序遍歷
func PreTraversal1(pRoot *BinaryTree) {
stack := make([]*BinaryTree, 0)
for nil != pRoot {
if nil != pRoot {
//訪問根節點
if v, ok := pRoot.Value.(Bter); ok {
v.Print()
}
//右節點先入棧
if nil != pRoot.pRight {
stack = append(stack, pRoot.pRight)
}
//訪問左節點
pRoot = pRoot.pLeft
}
//左節點訪問完 右節點出棧
if nil == pRoot && len(stack) > 0 {
pRoot = stack[len(stack)-1]
stack = stack[:len(stack)-1]
}
}
}
//Middle order traversal binary tree
func MidTraversal(pRoot *BinaryTree) {
if nil != pRoot {
MidTraversal(pRoot.pLeft)
if v, ok := pRoot.Value.(Bter); ok {
v.Print()
}
MidTraversal(pRoot.pRight)
}
}
//非遞歸中序遍歷
func MidTraversal1(pRoot *BinaryTree) {
stack := make([]*BinaryTree, 0)
for nil != pRoot {
//根節點入棧
stack = append(stack, pRoot)
pRoot = pRoot.pLeft//先訪問左節點
for nil == pRoot && len(stack) > 0 {
pRoot = stack[len(stack)-1]
stack = stack[:len(stack)-1]
if v, ok := pRoot.Value.(Bter); ok {
v.Print()
}
pRoot = pRoot.pRight
}
}
}
//Post order traversal binary tree
func PostTraversal(pRoot *BinaryTree) {
if nil != pRoot {
PostTraversal(pRoot.pLeft)
PostTraversal(pRoot.pRight)
if v, ok := pRoot.Value.(Bter); ok {
v.Print()
}
}
}
//非遞歸後序遍歷
func PostTraversal1(pRoot *BinaryTree) {
stack := make([]*BinaryTree, 0)
//後序遍歷需要訪問父節點的左右孩子節點 需要輔助HASH標記是否訪問過
m := make(map[*BinaryTree]struct{})
for nil != pRoot {
stack = append(stack, pRoot)
pRoot = pRoot.pLeft
for nil == pRoot && len(stack) > 0 {
pRoot = stack[len(stack)-1]
if _, ok := m[pRoot]; !ok {
m[pRoot] = struct{}{}
pRoot = pRoot.pRight
} else {
stack = stack[:len(stack)-1]
if v, ok := pRoot.Value.(Bter); ok {
v.Print()
}
pRoot = nil
}
}
}
}