Go 数据结构--二分查找树
Go 数据结构--二分查找树
今天开始一个Go实现常见数据结构的系列吧。有时间会更新其他数据结构。
一些概念
二叉树:二叉树是每个节点最多有两个子树的树结构。
完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
满二叉树:除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
平衡二叉树:平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
二叉查找树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二叉搜索树原理
二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).
实现
上述基本是百度百科的概念,现在来直接上实现代码:
/*
时间:2017/8/24
功能:二叉树
*/
package main
import (
"fmt"
"sync"
)
//二叉树节点结构
type Node struct {
data int
left *Node
right *Node
}
//二叉查找树结构
type BST struct {
root *Node
lock sync.RWMutex
}
//插入方法(判断位置 中序遍历)
func insertNode(node *Node, addNode *Node) {
if addNode.data < node.data {
if node.left == nil {
node.left = addNode
} else {
insertNode(node.left, addNode)
}
} else {
if node.right == nil {
node.right = addNode
} else {
insertNode(node.right, addNode)
}
}
}
//插入操作
func (t *BST) Insert(data int) {
t.lock.Lock()
defer t.lock.Unlock()
node := &Node{
data: data,
left: nil,
right: nil,
}
if t.root == nil {
t.root = node
} else {
insertNode(t.root, node)
}
}
//先序遍历
func PreOrderTraverse(bst *Node) {
if bst != nil {
fmt.Printf("%d ", bst.data)
PreOrderTraverse(bst.left)
PreOrderTraverse(bst.right)
}
}
//中序遍历
func InOrderTraverse(bst *Node) {
if bst != nil {
InOrderTraverse(bst.left)
fmt.Printf("%d ", bst.data)
InOrderTraverse(bst.right)
}
}
//后序遍历
func PostOrderTraverse(bst *Node) {
if bst != nil {
PostOrderTraverse(bst.left)
PostOrderTraverse(bst.right)
fmt.Printf("%d ", bst.data)
}
}
//查找
func SearchBST(node *Node, key int) bool {
if node == nil {
return false
}
if key == node.data {
return true
}
if key < node.data {
return SearchBST(node.left, key)
} else {
return SearchBST(node.right, key)
}
}
//删除执行函数
func remove(node *Node, key int) *Node {
if node == nil {
return nil
}
if key == node.data {
if node.left == nil && node.right == nil {
node = nil
return nil
}
if node.left == nil {
node = node.right
return node
}
if node.right == nil {
node = node.left
return node
}
rightside := node.right
for {
if rightside != nil && rightside.left != nil {
rightside = rightside.left
} else {
break
}
}
node.data = rightside.data
node.right = remove(node.right, node.data)
return node
}
if key < node.data {
node.left = remove(node.left, key)
return node
} else {
node.right = remove(node.right, key)
return node
}
}
//删除操作
func (t *BST) Remove(key int) {
t.lock.Lock()
defer t.lock.Unlock()
remove(t.root, key)
}
func main() {
var t BST
t.Insert(2)
t.Insert(6)
t.Insert(5)
t.Insert(1)
t.Insert(10)
t.Insert(8)
fmt.Println("PREORDER...")
PreOrderTraverse(t.root)
fmt.Println("\nINORDER...")
InOrderTraverse(t.root)
fmt.Println("\nPOSTORDER...")
PostOrderTraverse(t.root)
fmt.Printf("\n")
fmt.Println("Search...")
fmt.Println(SearchBST(t.root, 6))
fmt.Println("Remove...")
t.Remove(6)
fmt.Println("PREORDER...")
PreOrderTraverse(t.root)
fmt.Println("\nINORDER...")
InOrderTraverse(t.root)
fmt.Println("\nPOSTORDER...")
PostOrderTraverse(t.root)
fmt.Printf("\n")
fmt.Println("Search...")
fmt.Println(SearchBST(t.root, 6))
}
执行结果
PREORDER...
2 1 6 5 10 8
INORDER...
1 2 5 6 8 10
POSTORDER...
1 5 8 10 6 2
Search...
true
Remove...
PREORDER...
2 1 8 5 10
INORDER...
1 2 5 8 10
POSTORDER...
1 5 10 8 2
Search...
false
总结
照例得总结一波,其实每什么好总结的,大家都熟悉的数据结构。在增删查的复杂度比较均衡。拿来练手非常不错。
Go 数据结构--二分查找树的更多相关文章
- lintcode-106-排序列表转换为二分查找树
106-排序列表转换为二分查找树 给出一个所有元素以升序排序的单链表,将它转换成一棵高度平衡的二分查找树 样例 标签 递归 链表 思路 类似于二分查找,每次将链表二分,中间节点作为根节点,在建立左子树 ...
- 笔试算法题(58):二分查找树性能分析(Binary Search Tree Performance Analysis)
议题:二分查找树性能分析(Binary Search Tree Performance Analysis) 分析: 二叉搜索树(Binary Search Tree,BST)是一颗典型的二叉树,同时任 ...
- 手把手教你用java实现二分查找树及其相关操作
二分查找树(Binary Search Tree)的基本操作有搜索.求最大值.求最小值.求前继.求后继.插入及删除. 对二分查找树的进行基本操作所花费的时间与树的高度成比例.例如有n个节点的完全二叉树 ...
- 数据结构---平衡查找树之B树和B+树(转)
本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...
- SPOJ TEMPLEQ - Temple Queues(二分查找+树状数组)
题意: 有N个队伍(1 <= N <= 100,000),每个队伍开始有ai个人[0 <= ai<= 100,000,000],有Q个操作[0<=Q<= 500,0 ...
- python数据结构之树(二分查找树)
本篇学习笔记记录二叉查找树的定义以及用python实现数据结构增.删.查的操作. 二叉查找树(Binary Search Tree) 简称BST,又叫二叉排序树(Binary Sort Tree),是 ...
- Holedox Eating HDU - 4302 2012多校C 二分查找+树状数组/线段树优化
题意 一个长度$n<=1e5$的数轴,$m<=1e5$个操作 有两种一些操作 $0$ $x$ 在$x$放一个食物 $1$ 一个虫子去吃最近的食物,如果有两个食物一样近,不转变方向的去吃 ...
- 二分查找树按照key值划分
#include <iostream>#include <vector>#include <algorithm>#include <string>#in ...
- js二分查找树实现
function BinaryTree() { var Node = function(key) { this.key = key; this.left = null; this.right = nu ...
随机推荐
- Unity3D拖尾组件在Ui界面下正常显示
在项目中Canvas下UI添加拖尾效果,会发现Ui完全遮挡住了拖尾. 如果要正常显示通常需要对Canvas进行设置,Render Mode 我这里用的是-Camera模式 其次要对Material 下 ...
- 搭建SSM项目框架全过程及思考
1.前言 之前都是在现有框架下进行写代码或者总是看一些别人的架构,总会眼高手低.于是打算自己完整的走一遍流程,同时把所遇到的问题,思考的问题记下来,供大家参考.由于是工作年限不高,属于新手,不足之处还 ...
- vue的增删改查
我们把这些用户信息保存到list的数组中,然后增删改查就在这个数组上进行: list: [ { username: 'aaaaa', email: '123@qq.com', sex: '男', pr ...
- Win Linux 双系统安装指南
双系统安装指南 环境说明 硬件:一块240G NVMe,一块240G SSD,一块2T的HDD. 系统:Linux Mint 18.2,Windows 10 Enterprise Version 17 ...
- Go语言学习笔记(三)数组 & 切片 & map
加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 数组 Arrays 数组是同一种数据类型的固定长度的序列. 数组是值类型,因此改变副本的值,不会改变本身的值: 当 ...
- 在Jekyll博客添加评论系统:gitment篇
最近在Github Pages上使用Jekyll搭建了个人博客( jacobpan3g.github.io/cn ), 当需要添加评论系统时,找了一下国内的几个第三方评论系统,如"多说&qu ...
- docker~docker-machine的介绍
回到目录 国外的hub.ducker.com速度确实有些慢,还好,有咱们的阿里云,今天和大家聊聊通过添加docker-machine来改变docker的hub服务器,最终来加速咱们下载镜像的速度! 工 ...
- (转)java中的 | ^ & 分别是什么?
|是按位或 ^是按位抑或 &是按位与 比如有两个数 int x = 5; int y = 11; System.out.println(x|y); System.out.println(x&a ...
- Windows Server 2008 配置IIS+PHP
问题: 最近要上线一个PHP写成的MVC项目,发现Windows Server 2008安装的还是PHP5.2,很多语法不支持. 尝试的一些解决方案: 1.将PHP升级为5.6,但是需要做好IIS和P ...
- if else 和switch case以及continue,break的区别
1,if 经常用于做区间判断 或者 固定值: break和continue的使用 break:用来结束循环结构或者switch case continue:结束此次循环进入 ...