直擊面試之二叉樹

面試過程中經常會問到二叉樹相關的問題,下面使用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
			}
		}
	}
}

 

發佈了58 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章