当前位置: 首页 > news >正文

《go语言程序设计》学习(七)

一,omap(真是个不幸的消息,把细节看了一下,然后填了东西测试,发现这个实现有bug。。。不过作为结构的学习,还是可以的)

// Copyright © 2011-12 Qtrac Ltd.
// 
// This program or package and any associated files are licensed under the
// Apache License, Version 2.0 (the "License"); you may not use these files
// except in compliance with the License. You can get a copy of the License
// at: http://www.apache.org/licenses/LICENSE-2.0.
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// The data structure is a left-leaning red-black tree based on Robert
// Sedgewick's implementations as described in
// http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf and
// http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf, with some of
// the code based on Lee Stanza's C++ code at
// http://www.teachsolaisgames.com/articles/balanced_left_leaning.html
// Thanks also to Russ Cox for many useful suggestions.

// Package omap implements an efficient key-ordered map.
//
// Keys and values may be of any type, but all keys must be comparable
// using the less than function that is passed in to the omap.New()
// function, or the less than function provided by the omap.New*()
// construction functions.
package omap

import "strings"

// NewStringKeyed returns an empty Map that accepts case-sensitive
// string keys.
func NewStringKeyed() *Map {
    return &Map{less: func(a, b interface{}) bool {
        return a.(string) < b.(string)
    }}
}

// NewCaseFoldedKeyed returns an empty Map that accepts case-insensitive
// string keys.
func NewCaseFoldedKeyed() *Map {
    return &Map{less: func(a, b interface{}) bool {
        return strings.ToLower(a.(string)) < strings.ToLower(b.(string))
    }}
}

// NewIntKeyed returns an empty Map that accepts int keys.
func NewIntKeyed() *Map {
    return &Map{less: func(a, b interface{}) bool {
        return a.(int) < b.(int)
    }}
}

// NewFloat64Keyed returns an empty Map that accepts float64 keys.
func NewFloat64Keyed() *Map {
    return &Map{less: func(a, b interface{}) bool {
        return a.(float64) < b.(float64)
    }}
}

// New returns an empty Map that uses the given less than function to
// compare keys. For example:
//      type Point { X, Y int }
//      pointMap := omap.New(func(a, b interface{}) bool {
//              α, β := a.(Point), b.(Point)
//              if α.X != β.X {
//                  return α.X < β.X
//              }
//              return α.Y < β.Y
//          })
func New(less func(interface{}, interface{}) bool) *Map {
    return &Map{less: less}
}

// Map is a key-ordered map.
// The zero value is an invalid map! Use one of the construction functions
// (e.g., New()), to create a map for a specific key type.
type Map struct {
    root   *node
    less   func(interface{}, interface{}) bool
    length int
}

type node struct {
    key, value  interface{}
    red         bool
    left, right *node
}

// Insert inserts a new key-value into the Map and returns true; or
// replaces an existing key-value pair's value if the keys are equal and
// returns false. For example:
//      inserted := myMap.Insert(key, value).
func (m *Map) Insert(key, value interface{}) (inserted bool) {
    m.root, inserted = m.insert(m.root, key, value)
    m.root.red = false
    if inserted {
        m.length++
    }
    return inserted
}

// Find returns the value and true if the key is in the Map or nil and
// false otherwise. For example:
//      value, found := myMap.Find(key).
func (m *Map) Find(key interface{}) (value interface{}, found bool) {
    root := m.root
    for root != nil {
        if m.less(key, root.key) {
            root = root.left
        } else if m.less(root.key, key) {
            root = root.right
        } else {
            return root.value, true
        }
    }
    return nil, false
}

// Delete deletes the key-value with the given key from the Map and returns
// true, or does nothing and returns false if there is no key-value with
// the given key. For example:
//      deleted := myMap.Delete(key).
func (m *Map) Delete(key interface{}) (deleted bool) {
    if m.root != nil {
        if m.root, deleted = m.remove(m.root, key); m.root != nil {
            m.root.red = false
        }
    }
    if deleted {
        m.length--
    }
    return deleted
}

// Do calls the given function on every key-value in the Map in order.
func (m *Map) Do(function func(interface{}, interface{})) {
    do(m.root, function)
}

// Len returns the number of key-value pairs in the map.
func (m *Map) Len() int {
    return m.length
}

func (m *Map) insert(root *node, key, value interface{}) (*node, bool) {
    inserted := false
    if root == nil { // If the key was in the tree it would belong here
        return &node{key: key, value: value, red: true}, true
    }
    if isRed(root.left) && isRed(root.right) {
        colorFlip(root)
    }
    if m.less(key, root.key) {
        root.left, inserted = m.insert(root.left, key, value)
    } else if m.less(root.key, key) {
        root.right, inserted = m.insert(root.right, key, value)
    } else { // The key is already in the tree so just replace its value
        root.value = value
    }
    if isRed(root.right) && !isRed(root.left) {
        root = rotateLeft(root)
    }
    if isRed(root.left) && isRed(root.left.left) {
        root = rotateRight(root)
    }
    return root, inserted
}

func isRed(root *node) bool { return root != nil && root.red }

func colorFlip(root *node) {
    root.red = !root.red
    if root.left != nil {
        root.left.red = !root.left.red
    }
    if root.right != nil {
        root.right.red = !root.right.red
    }
}

func rotateLeft(root *node) *node {
    x := root.right
    root.right = x.left
    x.left = root
    x.red = root.red
    root.red = true
    return x
}

func rotateRight(root *node) *node {
    x := root.left
    root.left = x.right
    x.right = root
    x.red = root.red
    root.red = true
    return x
}

func do(root *node, function func(interface{}, interface{})) {
    if root != nil {
        do(root.left, function)
        function(root.key, root.value)
        do(root.right, function)
    }
}

// We do not provide an exported First() method because this is an
// implementation detail.
func first(root *node) *node {
    for root.left != nil {
        root = root.left
    }
    return root
}

func (m *Map) remove(root *node, key interface{}) (*node, bool) {
    deleted := false
    if m.less(key, root.key) {
        if root.left != nil {
            if !isRed(root.left) && !isRed(root.left.left) {
                root = moveRedLeft(root)
            }
            root.left, deleted = m.remove(root.left, key)
        }
    } else {
        if isRed(root.left) {
            root = rotateRight(root)
        }
        if !m.less(key, root.key) && !m.less(root.key, key) &&
            root.right == nil {
            return nil, true
        }
        if root.right != nil {
            if !isRed(root.right) && !isRed(root.right.left) {
                root = moveRedRight(root)
            }
            if !m.less(key, root.key) && !m.less(root.key, key) {
                smallest := first(root.right)
                root.key = smallest.key
                root.value = smallest.value
                root.right = deleteMinimum(root.right)
                deleted = true
            } else {
                root.right, deleted = m.remove(root.right, key)
            }
        }
    }
    return fixUp(root), deleted
}

func moveRedLeft(root *node) *node {
    colorFlip(root)
    if root.right != nil && isRed(root.right.left) {
        root.right = rotateRight(root.right)
        root = rotateLeft(root)
        colorFlip(root)
    }
    return root
}

func moveRedRight(root *node) *node {
    colorFlip(root)
    if root.left != nil && isRed(root.left.left) {
        root = rotateRight(root)
        colorFlip(root)
    }
    return root
}

func deleteMinimum(root *node) *node {
    if root.left == nil {
        return nil
    }
    if !isRed(root.left) && !isRed(root.left.left) {
        root = moveRedLeft(root)
    }
    root.left = deleteMinimum(root.left)
    return fixUp(root)
}

func fixUp(root *node) *node {
    if isRed(root.right) {
        root = rotateLeft(root)
    }
    if isRed(root.left) && isRed(root.left.left) {
        root = rotateRight(root)
    }
    if isRed(root.left) && isRed(root.right) {
        colorFlip(root)
    }
    return root
}

嗯。。书中带的一个omap包。

最下面,是红黑树的具体实现,中间是红黑树的一个封装(插入,查询,遍历,删除等),最上面定义了几种less方法来实现多态(这应该是多态吧?)。

 

红黑树的旋转也没啥说的。。简单说一下这个插入吧。

注意看map结构和node结构。

当插入一个{key,value}的时候,是递归的遍历树,遍历方法就是使用less分别比较一个"根"节点key比较,小则放在左边,大则放在右边,否则更新“根”的value值。递归的更新完成之后,需要进行旋转,保持红黑树的染色特性。

转载于:https://www.cnblogs.com/mruoli/p/4704459.html

相关文章:

  • Android NDK revision 7 Host 'awk' tool is outda...
  • VLAN的Hybrid和Trunk端口有何区别
  • 运行时库链接错误的修复方法
  • python def和lambda的一点心得
  • Mysql几种索引类型的区别及适用情况
  • 怎么将一个类的成员函数作为指针传递给另一个类的成员函数
  • Linux下安装MySQL
  • 新手ui设计师必备——切图规范
  • 查询条件字段做运算优化
  • 很全的SQL注入语句,有SQL漏洞的都可以拿下
  • [转]WIN7系统安装Apache 提示msvcr110.DLL
  • Linux上的avahi-daemon Service服务
  • sqlite3 C language API简单例子
  • 用Hadoop进行分布式并行编程(二)
  • Memcached分布式算法详解
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • extjs4学习之配置
  • iOS编译提示和导航提示
  • jdbc就是这么简单
  • Nodejs和JavaWeb协助开发
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 电商搜索引擎的架构设计和性能优化
  • 盘点那些不知名却常用的 Git 操作
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 深入浅出Node.js
  • 微服务核心架构梳理
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (黑马C++)L06 重载与继承
  • (译) 函数式 JS #1:简介
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net 验证控件和javaScript的冲突问题
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .Net各种迷惑命名解释
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .sys文件乱码_python vscode输出乱码
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • /3GB和/USERVA开关
  • @Query中countQuery的介绍
  • @SuppressWarnings注解
  • [ai笔记4] 将AI工具场景化,应用于生活和工作
  • [Android]使用Git将项目提交到GitHub
  • [Angular] 笔记 20:NgContent
  • [jQuery]div滚动条回到最底部
  • [LeetCode]-Spiral Matrix III 螺旋矩阵
  • [nginx] 网上最全面nginx教程(近100篇文章整理)
  • [ssh]如何设计ARM板上多用户key登录系统
  • [tarjan][hdu 1269]
  • [Thinking]三个行
  • [Unity3d for android]屏幕触摸事件