golang 实现 二分查找 差值差值 红黑树查找算法
2019-08-06 14:34
411 查看
原文链接:https://blog.csdn.net/qq_25870633/article/details/82705217
这几个查找算法其实放在一根文件里面都可以但是为了可读性比较高一些我就分别放了
lookup.go 入口文件
package helper //二分查找 有序查找 func binarySearch4(arr []int, k int) int { low := 0 high := len(arr) - 1 for low <= high { /** 利用位与(&)提取出两个数相同的部分,利用异或(^)拿出两个数不同的部分的和,相同的部分加上不同部分的和除2即得到两个数的平均值 异或: 相同得零,不同得1 == 男男等零,女女得零,男女得子 avg = (a&b) + (a^b)>>1; 或者 avg = (a&b) + (a^b)/2; */ mid := low&high + (low^high)>>1 if k < arr[mid] { high = mid - 1 } else if k > arr[mid] { low = mid + 1 } else { return mid } } return -1 } //差值查找 有序查找 func insertSearch(arr []int, key int) int { low := 0 high := len(arr) - 1 time := 0 for low < high { time += 1 // 计算mid值是插值算法的核心代码 实际上就是 mid := low + int((high-low)*(key-arr[low])/(arr[high]-arr[low])) if key < arr[mid] { high = mid - 1 } else if key > arr[mid] { low = mid + 1 } else { return mid } } return -1 } /** 基本思路:先把数组构造出一颗二叉树的样纸,然后查找的时候在从root往下对比 */ func BSTsearch(arr []int, key int) int { // 先在内存中构造 二叉树 tree := new(Tree) for i, v := range arr { Insert(tree, v, i) } // 开始二叉树查找目标key return searchKey(tree.Root, key) } /** 红黑树查找 */ func RedBlackTreeSearch(arr []int, key int) int { // 先构造树 //tree := new(RBTree) tree := new(RBTree) for i, v := range arr { insertValue(tree, v, i) } // 开始二叉树查找目标key return tree.serch(key) }
BinaryTree.go 二分查找文件
package helper // 节点结构 type Node struct { Value, Index int // 元素的值和在数组中的位置 Left, Right *Node } // 树结构 type Tree struct { Root *Node } // 把数组的的元素插入树中 func Insert(tree *Tree, value, index int) { if nil == tree.Root { tree.Root = newNode(value, index) } else { InsertNode(tree.Root, newNode(value, index)) } } // 把新增的节点插入树的对应位置 func InsertNode(root, childNode *Node) { // 否则,先和根的值对比 if childNode.Value <= root.Value { // 如果小于等于跟的值,则插入到左子树 if nil == root.Left { root.Left = childNode } else { InsertNode(root.Left, childNode) } } else { // 否则,插入到右子树 if nil == root.Right { root.Right = childNode } else { InsertNode(root.Right, childNode) } } } func newNode(value, index int) *Node { return &Node{ Value: value, Index: index, } } // 在构建好的二叉树中,从root开始往下查找对应的key 返回其在数组中的位置 func searchKey(root *Node, key int) int { if nil == root { return -1 } if key == root.Value { return root.Index } else if key < root.Value { // 往左子树查找 return searchKey(root.Left, key) } else { // 往右子树查找 return searchKey(root.Right, key) } }
RedBlackTree.go 红黑树文件
package helper const ( RED = true BLACK = false ) // 节点 type RBNode struct { Color bool // true == 红 false == 黑 Parent, Left, Right *RBNode Value, Index int } type RBTree struct { Root *RBNode } /* * 对红黑树的节点(x)进行左旋转 * * 左旋示意图(对节点 x 进行左旋): * px px * / / * x y * / \ --(左旋)-. / \ # * lx y x ry * / \ / \ * ly ry lx ly * * */ func (t *RBTree) leftSpin(node *RBNode) { // 先提出自己的 右子 y := node.Right // 自己的新右子 是前右子的左子 node.Right = y.Left if nil != y.Left { y.Left.Parent = node } // 你以前的爹,就是我现在的爹 y.Parent = node.Parent // 如果被旋转的节点是 之前树的根 // 那么,新的跟就是 y 节点 if nil == node.Parent { t.Root = y } else { // 被旋转的是普通节点时, 需要结合自身的父亲来确认自己之前是属于 左子还是右子 if node.Parent.Left == node { // 被旋转节点之前是 左子时 // 用 y 来作为之前 该节点父亲的 新左子 node.Parent.Left = y } else { // 否则,是 右子 node.Parent.Right = y } } // 将 node 设为 y 的左子 y.Left = node // 将 y 设为 node 的新父亲 node.Parent = y } /* * 对红黑树的节点(y)进行右旋转 * * 右旋示意图(对节点 y 进行左旋): * py py * / / * y x * / \ --(右旋)-. / \ # * x ry lx y * / \ / \ # * lx rx rx ry * */ func (t *RBTree) rightSpin(node *RBNode) { // 先提出自己的 左子 x := node.Left node.Left = x.Right if nil != x.Left { x.Right.Parent = node } x.Parent = node.Parent // 如果被旋转的节点是 之前树的根 // 那么,新的跟就是 x 节点 if nil == node.Parent { t.Root = x } else { if node.Parent.Right == node { node.Parent.Right = x } else { node.Parent.Left = x } } x.Right = node node.Parent = x } func insertValue(tree *RBTree, val, index int) { node := &RBNode{Value: val, Index: index, Color: BLACK} if nil == tree.Root { tree.Root = node } else { tree.insert(node) } } func (t *RBTree) insert(node *RBNode) { //int cmp; var tmpNode *RBNode root := t.Root // 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。 for nil != root { if node.Value < root.Value { root = root.Left } else { root = root.Right } tmpNode = root } node.Parent = tmpNode if nil != tmpNode { if node.Value < tmpNode.Value { tmpNode.Left = node } else { tmpNode.Right = node } } else { t.Root = node } // 2. 设置节点的颜色为红色 node.Color = RED // 3. 将它重新修正为一颗二叉查找树 t.adjustRBTree(node) } // 修正树 func (t *RBTree) adjustRBTree(node *RBNode) { var parent, gparent *RBNode // 父亲 和 祖父 // 若“父节点存在,并且父节点的颜色是红色” for nil != node.Parent && RED == node.Parent.Color { parent = node.Parent gparent = parent.Parent //若“父节点”是“祖父节点的左孩子” if parent == gparent.Left { // Case 1条件:叔叔节点是红色 uncle := gparent.Right if nil != uncle && RED == uncle.Color { uncle.Color = BLACK parent.Color = BLACK gparent.Color = RED node = gparent continue } // Case 2条件:叔叔是黑色,且当前节点是右孩子 if node == parent.Right { var tmp *RBNode t.leftSpin(parent) tmp = parent parent = node node = tmp } // Case 3条件:叔叔是黑色,且当前节点是左孩子。 parent.Color = BLACK gparent.Color = RED t.rightSpin(gparent) } else { //若“z的父节点”是“z的祖父节点的右孩子” // Case 1条件:叔叔节点是红色 uncle := gparent.Left if nil != uncle && RED == uncle.Color { uncle.Color = BLACK parent.Color = BLACK gparent.Color = RED node = gparent continue } // Case 2条件:叔叔是黑色,且当前节点是左孩子 if node == parent.Left { var tmp *RBNode t.rightSpin(parent) tmp = parent parent = node node = tmp } // Case 3条件:叔叔是黑色,且当前节点是右孩子。 parent.Color = BLACK gparent.Color = RED t.leftSpin(gparent) } } // 将根节点设为黑色 t.Root.Color = BLACK } func (t *RBTree) serch(key int) int { return serch(t.Root, key) } func serch(node *RBNode, key int) int { if nil == node { return -1 } if key < node.Value { return serch(node.Left, key) } else if key > node.Value { return serch(node.Right, key) } else { return node.Index } }
相关文章推荐
- 基本查找算法 PHP 实现 保存 顺序查找,二分查找 分块查找
- golang实现二分查找
- 查找算法总结(顺序查找、二分查找、二叉树、平衡二叉树、红黑树、散列表hash)
- 查找算法之二分查找的C++实现
- 查找算法总结(顺序查找、二分查找、二叉树、平衡二叉树、红黑树、散列表hash)
- [查找算法]--二分查找的Java实现
- 查找算法的实现——二分查找
- Java实现的两种常见简单查找算法示例【快速查找与二分查找】
- java实现查找算法——折半查找(二分查找)
- 有序查找算法(二分查找、差值查找、斐波那契查找)
- 一个递归和非递归实现二分查找的代码
- 二分查找的实现
- 算法-二分查找-python实现
- 二分查找(Binary Search)需要注意的问题,以及在数据库内核中的实现
- 旋转数组查找, 二分查找的递归于非递归实现
- 查找算法之折半查找(二分查找)
- 【Cuda并行编程之一】二分查找的探究以及Cuda的简单实现&&相关面试题介绍
- 查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
- 二分查找的各种情况实现以及一些注意点
- C语言实现二分查找