• Home
  • About
    • Shadow Knight photo

      Shadow Knight

      https://live.bilibili.com/9565678

    • Learn More
    • Twitter
    • Facebook
    • Instagram
    • Github
    • Steam
  • Posts
    • All Posts
    • All Tags
  • Projects

go-二叉树

16 May 2018

Reading time ~3 minutes

package main

import (
	"github.com/cheekybits/genny/generic"
	"sync"
	"fmt"
)

// Item interface{}
type Item generic.Type

// 节点结构体
type Node struct {
	key   int  //key,根据key进行节点插入
	value Item //Item interface{}
	left  *Node //left
	right *Node //right
}

// 二叉树结构体
type ItemBinarySearchTree struct {
	root *Node  // 根节点
	lock sync.RWMutex  //读写锁
}


/*

------------------------------------------------
                     ---[ 1
              ---[ 2
                     ---[ 3
       ---[ 4
                     ---[ 5
              ---[ 6
                     ---[ 7
---[ 8
              ---[ 9
       ---[ 10
              ---[ 11
------------------------------------------------

*/

// 格式化输出二叉搜索树
func (tree *ItemBinarySearchTree) String() {
	tree.lock.Lock()
	defer tree.lock.Unlock()

	fmt.Println("------------------------------------------------")
	stringify(tree.root, 0)
	fmt.Println("------------------------------------------------")
}

// 通过递归进行格式化输出
func stringify(n *Node, level int) {
	if n != nil {
		format := ""
		for i := 0; i < level; i++ {
			format += "       "
		}
		format += "---[ "
		level++

		stringify(n.left, level)
		fmt.Printf(format+"%d\n", n.key)
		stringify(n.right, level)

	}
}

// 构建ItemBinarySearchTree搜索二叉树插入节点的方法
// 有两个参数,一个是节点的key,另一个是value
func (tree *ItemBinarySearchTree) Insert(key int, value Item) {

	// 上锁
	tree.lock.Lock()
	// 解锁
	defer tree.lock.Unlock()

	// 创建一个节点
	node := &Node{key, value, nil, nil}

	if tree.root == nil {
		tree.root = node
	} else {
		// 以根节点为入口,插入新节点node
		insertNode(tree.root, node)
	}
}

func insertNode(node, newNode *Node) {
	// 判断节点插入到左边还是右边
	// 如果新节点的key小于根节点的key,插入到左边,否则插入到右边
	if newNode.key < node.key {

		if node.left == nil {
			node.left = newNode
		}else {
			// 通过递归插入新节点到左边
			insertNode(node.left, newNode)
		}

	} else {
		if node.right == nil {
			node.right = newNode
		}else {
			// 通过递归插入新节点到右边
			insertNode(node.right,newNode)
		}

	}
}

// 搜索二叉树中最小的值
func (tree *ItemBinarySearchTree) Min() *Item {
	// 读写锁上锁
	tree.lock.RLock()
	// 读写锁解锁
	defer tree.lock.RUnlock()

	// 取出二叉树根节点
	node := tree.root

	if node == nil {
		return nil
	}
	// 最小的值一定在左边,所以只需要处理左边的节点即可
	// while
	for {
		if node.left == nil {
			return &node.value
		}
		node = node.left
	}
}

// 搜索二叉树中最小的值
func (tree *ItemBinarySearchTree) Max() *Item {
	// 读写锁上锁
	tree.lock.RLock()
	// 读写锁解锁
	defer tree.lock.RUnlock()

	// 取出二叉树根节点
	node := tree.root

	if node == nil {
		return nil
	}
	// 最小的值一定在左边,所以只需要处理左边的节点即可
	// while
	for {
		if node.right == nil {
			return &node.value
		}
		node = node.right
	}
}


// 传入某个key,查询这个key是否存在于二叉树中
func (tree *ItemBinarySearchTree) Search(key int) bool {
	// 上锁
	tree.lock.RLock()
	// 解锁
	defer tree.lock.RUnlock()
	// 搜索,返回搜索的结果
	return search(tree.root, key)
}

// 10

//13
/*
------------------------------------------------
                     ---[ 1
              ---[ 2
                     ---[ 3
       ---[ 4
                     ---[ 5
              ---[ 6
                     ---[ 7
---[ 8
              ---[ 9
       ---[ 10
              ---[ 11
------------------------------------------------
*/
func search(n *Node, key int) bool {
	if n == nil {
		return false
	}

	if key < n.key {
		// 如果传入的key小于节点的key,往左边搜索
		return search(n.left, key)
	}

	if key > n.key {
		// 如果传入的key大于节点的key,往右边边搜索
		return search(n.right, key)
	}
	// 两个key相等返回true
	return true
}

// 中序遍历
func (bst *ItemBinarySearchTree) InOrderTraverse(f func(Item)) {
	bst.lock.RLock()
	defer bst.lock.RUnlock()

	inOrderTraverse(bst.root, f)
}

func inOrderTraverse(n *Node, f func(Item)) {
	if n != nil {
		inOrderTraverse(n.left, f) // L
		f(n.value) // D
		inOrderTraverse(n.right, f) // R
	}
}


// 后序遍历
func (bst *ItemBinarySearchTree) postOrderTraverse(f func(Item)) {
	bst.lock.RLock()
	defer bst.lock.RUnlock()

	postOrderTraverse(bst.root, f)
}

func postOrderTraverse(n *Node, f func(Item)) {
	if n != nil {
		postOrderTraverse(n.left, f) // L
		postOrderTraverse(n.right, f) // R
		f(n.value) // D
	}
}


// 前序遍历
func (bst *ItemBinarySearchTree) preOrderTraverse(f func(Item)) {
	bst.lock.RLock()
	defer bst.lock.RUnlock()

	preOrderTraverse(bst.root, f)
}

func preOrderTraverse(n *Node, f func(Item)) {
	if n != nil {
		f(n.value) // D
		preOrderTraverse(n.left, f) // L
		preOrderTraverse(n.right, f) // R
	}
}

func main()  {
	// 创建二叉搜索树对象
	// 0xc4200a4020
	var tree ItemBinarySearchTree
	// 打印tree
	//fmt.Println(tree)
	//fmt.Printf("%p",&tree)
	// 插入第一个节点
	tree.Insert(8, "8")
	tree.Insert(4, "4")
	tree.Insert(10, "10")
	tree.Insert(2, "2")
	tree.Insert(6, "6")
	tree.Insert(1, "1")
	tree.Insert(3, "3")
	tree.Insert(5, "5")
	tree.Insert(7, "7")
	tree.Insert(9, "9")
	tree.Insert(11, "11")

	tree.String()

	fmt.Printf("二叉树key最小的节点的value值:%v\n",*tree.Min())
	fmt.Printf("二叉树key最大的节点的value值:%v\n",*tree.Max())

	fmt.Println(tree.Search(13))

	f := func(i Item) {
		fmt.Println(i)
	}
	fmt.Println("---------------中序遍历--------------------")
	tree.InOrderTraverse(f)
	fmt.Println("---------------前序遍历--------------------")
	tree.preOrderTraverse(f)
	fmt.Println("---------------后序遍历--------------------")
	tree.postOrderTraverse(f)


}


二叉树 Share Tweet +1