はじめに
零細企業の事務をやっているおじさんです。Go歴は半年です。
螺旋本のpart3 第16章の16.13線分交差問題AOJ CGL6_JをGoで解こうとしたところ、そこに載っているサンプルコードでc++のlower_boundとupper_boundが、Goにはないようだったので、自作しました。
注意
・二分探索木で作っています
・イテレータではなく、Nodeを返します
・sliceには使えません
・初心者なので、ここで紹介しているものが不完全である可能性は十分あります
・四角い車輪の再発明の可能性大
Go版lower_boundのコード
func lowerBoundNode(n *Node, x interface{}) *Node {
	if n.key < x.(int) {
		if n.right != nil {
			n = lowerBoundNode(n.right, x)
		}
	} else if n.key >= x.(int) {
		if n.left != nil && n.left.key >= x.(int) {
			n = lowerBoundNode(n.left, x)
		}
	}
    return n
}
func (t *Tree) lowerBound(x interface{}) *Node {
	return lowerBoundNode(t.root, x)
}
t.lowerBound(x)で、x <= n.key となる最初の*Nodeを返します。
n.key < x なら右に行ってn.key >= xとなるノードを探し、n.key >= x なら左に行って最初のノードを探しています。
Go版upper_boundのコード
func upperBoundNode(n *Node, x interface{}) *Node {
	if n.key <= x.(int) {
		if n.right != nil {
			n = upperBoundNode(n.right, x)
		}
	} else if n.key > x.(int) {
		if n.left != nil && n.left.key > x.(int) {
			n = upperBoundNode(n.left, x)
		}
	}
    return n
}
func (t *Tree)upperBound(x interface{})*Node{
    return upperBoundNode(t.root,x)
}
t.upperBound(x)で、x < n.key となる最初の*Nodeを返します。
lowerBoundと大体同じです。
コード全部
[AOJ CGL6_J](https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/6/CGL_6_A,"AOJ CGL6_J")への提出用ではなく、AOJ ALDS1_8_Cへ提出したものを改変しています。
AOJ ALDS1_8_Cにある入力例を使用し実行→paiza.io
もしかしたらsetとして使えるかもしれませんが、多分遅いです。
package main
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)
var rdr = bufio.NewReaderSize(os.Stdin, 1024*1024)
func readLine() string {
	buf := []byte{}
	for {
		l, p, e := rdr.ReadLine()
		if e != nil {
			panic(e)
		}
		buf = append(buf, l...)
		if !p {
			break
		}
	}
	return string(buf)
}
func readInts() []int {
	s := strings.Split(readLine(), " ")
	res := []int{}
	for _, v := range s {
		i, _ := strconv.Atoi(v)
		res = append(res, i)
	}
	return res
}
type Node struct {
	key    int
	parent *Node
	left   *Node
	right  *Node
}
func NewNode() *Node {
	res := Node{}
	return &res
}
type Tree struct {
	root *Node
}
func NewTree() *Tree {
	res := Tree{
		root: nil,
	}
	return &res
}
// 先行順巡回アルゴリズムでNodeのkeyを返す
func (t *Tree) preParse(z *Node) string {
	if z == nil {
		return ""
	}
	return " " + strconv.Itoa(z.key) + t.preParse(z.left) + t.preParse(z.right)
}
// 中間順巡回アルゴリズムでNodeのkeyを返す
func (t *Tree) inParse(z *Node) string {
	//fmt.Println(z)
	if z == nil {
		return ""
	}
	return t.inParse(z.left) + " " + strconv.Itoa(z.key) + t.inParse(z.right)
}
func find(sl []int, x int) int {
	for i := 0; i < len(sl); i++ {
		if sl[i] == x {
			return i
		}
	}
	return -1
}
/*
1 insert(T, z)
2     y = NIL // x の親
3     x = 'T の根'
4     while x ≠ NIL
5         y = x // 親を設定
6         if z.key < x.key
7             x = x.left // 左の子へ移動
8         else
9             x = x.right // 右の子へ移動
10    z.p = y
11
12    if y == NIL // T が空の場合
13        'T の根' = z
14    else if z.key < y.key
15        y.left = z // z を y の左の子にする
16    else
17        y.right = z // z を y の右の子にする
*/
func (t *Tree) insert(k int) {
	//fmt.Println("k",k)
	x := t.root
	var y *Node
	//var flag bool=false
	for x != nil {
		y = x
		if k == x.key { //既にxをkeyに持つNodeがあった場合
			return
		} else if k < x.key {
			x = x.left
		} else {
			x = x.right
		}
	}
	var new_node *Node
	new_node = &Node{left: nil, right: nil, key: k}
	new_node.parent = y
	if y == nil {
		t.root = new_node
	} else if new_node.key < y.key {
		y.left = new_node
	} else {
		y.right = new_node
	}
	//fmt.Println(new_node)
}
func (t *Tree) find(k int) *Node {
	x := t.root
	for x != nil && k != x.key {
		if k < x.key {
			x = x.left
		} else {
			x = x.right
		}
	}
	return x
}
func (t *Tree) deleteNode(z *Node) {
	//yを削除対象とする
	var y *Node
	if z.left == nil || z.right == nil {
		y = z
	} else {
		y = getSuccessor(z)
	}
	//yの子xを決める
	var x *Node
	if y.left != nil {
		x = y.left
	} else {
		x = y.right
	}
	//yの親を設定する
	if x != nil {
		x.parent = y.parent
	}
	// 削除する
	if y.parent == nil {
		t.root = x
	} else if y == y.parent.left {
		y.parent.left = x
	} else {
		y.parent.right = x
	}
	if y != z {
		z.key = y.key
	}
}
func getSuccessor(x *Node) *Node {
	if x.right != nil {
		return getMinimum(x.right)
	}
	var y *Node
	y = x.parent
	for y != nil && x == y.right {
		x = y
		y = y.parent
	}
	return y
}
func getMinimum(x *Node) *Node {
	for x.left != nil {
		x = x.left
	}
	return x
}
func lowerBoundNode(n *Node, x interface{}) *Node {
	if n.key < x.(int) {
		if n.right != nil {
			n = lowerBoundNode(n.right, x)
		}
	} else if n.key >= x.(int) {
		if n.left != nil && n.left.key >= x.(int) {
			n = lowerBoundNode(n.left, x)
		}
	}
	return n
}
func (t *Tree) lowerBound(x interface{}) *Node {
	return lowerBoundNode(t.root, x)
}
func upperBoundNode(n *Node, x interface{}) *Node {
	//fmt.Println("lowerBoundNode n:",&n,n,"x",x)
	if n.key <= x.(int) {
		if n.right != nil {
			n = upperBoundNode(n.right, x)
		}
	} else if n.key > x.(int) {
		if n.left != nil && n.left.key > x.(int) {
			n = upperBoundNode(n.left, x)
		}
	}
	return n
}
func (t *Tree) upperBound(x interface{}) *Node {
	return upperBoundNode(t.root, x)
}
func main() {
	n := readInts()[0]
	t := NewTree()
	//fmt.Println(n,*t)
	for i := 0; i < n; i++ {
		tmp := strings.Split(readLine(), " ")
		if tmp[0] == "insert" {
			v, _ := strconv.Atoi(tmp[1])
			t.insert(v)
		} else if tmp[0] == "print" {
			fmt.Println(t.inParse(t.root))
			fmt.Println(t.preParse(t.root))
			fmt.Println("t.root", t.root)
			fmt.Println("t.lowerBound(t.root,x)", t.lowerBound(1))
			fmt.Println("t.upperBound(t.root,x)", t.upperBound(1))
		} else if tmp[0] == "find" {
			v, _ := strconv.Atoi(tmp[1])
			res := t.find(v)
			if res != nil {
				fmt.Println("yes")
			} else {
				fmt.Println("no")
			}
		} else if tmp[0] == "delete" {
			v, _ := strconv.Atoi(tmp[1])
			//fmt.Println(t.find(v))
			t.deleteNode(t.find(v))
		}
	}
}
参考
お気楽 Go 言語プログラミング入門(二分探索木)
プログラミングコンテスト攻略のためのアルゴリズムとデータ構造(Amazon)
https://cpprefjp.github.io/reference/set/set/lower_bound.html
https://cpprefjp.github.io/reference/set/set/upper_bound.html
