github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/omap/osmaps/osmaps.go (about)

     1  package osmaps
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strconv"
     7  
     8  	"github.com/pbberlin/tools/util"
     9  )
    10  
    11  const (
    12  	zeroVal   = ""
    13  	cFanout   = 12   // key-values per node
    14  	cPrealloc = 1500 // kv-slices pre-allocated on map-creation
    15  
    16  	noSuccessor = -1 // constant indicating no successor
    17  )
    18  
    19  var (
    20  	cntr   = 0
    21  	ndStat = make([]map[*node]int, 20) // node statistics
    22  )
    23  
    24  func init() {
    25  	for i := 0; i < len(ndStat); i++ {
    26  		ndStat[i] = make(map[*node]int, 0)
    27  	}
    28  }
    29  
    30  // key-value type
    31  type kvt struct {
    32  	key, val string
    33  	succ     int
    34  }
    35  
    36  type OSMap struct {
    37  	root   *node
    38  	less   func(string, string) bool
    39  	length int
    40  
    41  	reservoir [][]kvt
    42  	allocCntr int
    43  }
    44  
    45  type node struct {
    46  	min, max string // key
    47  	minIdx   int    // index to smallest key
    48  	kv       []kvt
    49  
    50  	red         bool
    51  	left, right *node
    52  }
    53  
    54  // New returns an empty Map
    55  func New() *OSMap {
    56  	f := func(a, b string) bool {
    57  		return a < b
    58  	}
    59  	m := &OSMap{less: f}
    60  
    61  	x := make([][]kvt, cPrealloc)
    62  	for i := 0; i < len(x); i++ {
    63  		x[i] = make([]kvt, 0, cFanout)
    64  	}
    65  	m.reservoir = x
    66  	return m
    67  }
    68  
    69  // Insert inserts a new key-value into the Map returning true;
    70  // or replaces an existing key-value pair's value returning false.
    71  //      inserted := myMap.Insert(key, value).
    72  func (m *OSMap) Insert(key, value string) (inserted bool) {
    73  	m.root, inserted = m.insert(m.root, key, value, 0)
    74  	m.root.red = false
    75  	if inserted {
    76  		m.length++
    77  	}
    78  	return inserted
    79  }
    80  
    81  // For compatibility
    82  func (m *OSMap) Set(key, value string) (inserted bool) { return m.Insert(key, value) }
    83  
    84  // Find returns the value and true if the key is in the Map
    85  // or nil and false otherwise.
    86  //      value, found := myMap.Find(key).
    87  func (m *OSMap) Find(key string) (value string, found bool) {
    88  	nd := m.root
    89  	for nd != nil {
    90  		if m.less(key, nd.min) && nd.left != nil {
    91  			nd = nd.left
    92  		} else if m.less(nd.max, key) && nd.right != nil {
    93  			nd = nd.right
    94  		} else {
    95  			_, value, found = findInner(nd, key)
    96  			return
    97  		}
    98  	}
    99  	return zeroVal, false // string null value
   100  }
   101  
   102  // For compatibility
   103  func (m *OSMap) Get(key string) (value string, found bool) { return m.Find(key) }
   104  
   105  // Delete deletes the key-value returning true,
   106  // or does nothing returning false
   107  //      deleted := myMap.Delete(key).
   108  func (m *OSMap) Delete(key string) (deleted bool) {
   109  	if m.root != nil {
   110  		if m.root, deleted = m.remove(m.root, key); m.root != nil {
   111  			m.root.red = false
   112  		}
   113  	}
   114  	if deleted {
   115  		m.length--
   116  	}
   117  	return deleted
   118  }
   119  
   120  // Do calls the given function
   121  // on every key-value in the Map in order.
   122  func (m *OSMap) Do(fct1 func(string, string)) {
   123  	do(m.root, fct1)
   124  }
   125  
   126  // Len returns the number of key-value pairs in the map.
   127  func (m *OSMap) Len() int {
   128  	return m.length
   129  }
   130  
   131  // ========================================================
   132  func INNER_CORE_FOR_EXTRACTION() {
   133  	// insert(args)
   134  	// do(args)
   135  	// remove(args)
   136  
   137  }
   138  
   139  func findInner(nd *node, key string) (idx int, val string, found bool) {
   140  
   141  	for i := 0; i < len(nd.kv); i++ {
   142  		if nd.kv[i].key == key {
   143  			return i, nd.kv[i].val, true
   144  		}
   145  	}
   146  	return noSuccessor, zeroVal, false
   147  
   148  }
   149  
   150  func (m *OSMap) insert(nd *node, key, value string, lvl int) (*node, bool) {
   151  	inserted := false
   152  
   153  	if nd == nil {
   154  		// If the key was in the tree it would belong here
   155  		newNd := node{}
   156  		newNd.red = true
   157  		newNd.min = key
   158  		newNd.max = key
   159  		newNd.kv = make([]kvt, 0, cFanout)
   160  		newNd.kv = append(newNd.kv, kvt{key, value, noSuccessor})
   161  		return &newNd, true
   162  	}
   163  
   164  	if isRed(nd.left) && isRed(nd.right) {
   165  		colorFlip(nd)
   166  	}
   167  
   168  	if m.less(key, nd.min) && nd.left != nil {
   169  		// printStatus("branch left", key, lvl)
   170  		nd.left, inserted = m.insert(nd.left, key, value, lvl+1)
   171  	} else if m.less(nd.max, key) && nd.right != nil {
   172  		// printStatus("branch rght", key, lvl)
   173  		nd.right, inserted = m.insert(nd.right, key, value, lvl+1)
   174  	} else {
   175  		// printStatus("remain", key, lvl)
   176  		idx, _, contains := findInner(nd, key)
   177  		if contains {
   178  			nd.kv[idx].val = value // update
   179  		} else {
   180  			inserted = insertLinkedList(nd, m.less, key, value)
   181  		}
   182  
   183  	}
   184  
   185  	if len(nd.kv) > cFanout-1 {
   186  		// -1 | split one step *before* reaching capacity
   187  		x := nd.right
   188  		nd.right = m.split(nd, lvl)
   189  		nd.right.right = x
   190  	}
   191  
   192  	//
   193  
   194  	if isRed(nd.right) && !isRed(nd.left) {
   195  		nd = rotateLeft(nd)
   196  	}
   197  	if isRed(nd.left) && isRed(nd.left.left) {
   198  		nd = rotateRight(nd)
   199  	}
   200  	return nd, inserted
   201  }
   202  
   203  func (m *OSMap) split(nd *node, lvl int) *node {
   204  
   205  	sortedK := make([]string, len(nd.kv))
   206  	for i := 0; i < len(nd.kv); i++ {
   207  		sortedK[i] = nd.kv[i].key
   208  	}
   209  	sort.Strings(sortedK)
   210  
   211  	halfIdx := len(nd.kv) / 2
   212  	splitkey := sortedK[halfIdx]
   213  
   214  	ndStat[lvl][nd]++
   215  
   216  	if lvl == 4 || lvl == 6 {
   217  		kd := make([]string, 3)
   218  		kd[0], kd[1], kd[2] = sortedK[0], splitkey, sortedK[len(sortedK)-1]
   219  		for i := 0; i < len(kd); i++ {
   220  			kd[i] = kd[i][:util.Min(len(kd[i]), 3)]
   221  		}
   222  		// fmt.Printf("splitting l%2v ac%3v %4q <  %4q < %4q \n", lvl, m.allocCntr, kd[0], kd[1], kd[2])
   223  	}
   224  
   225  	// kv1 := make([]kvt, 0, cFanout)
   226  	// kv2 := make([]kvt, 0, cFanout)
   227  
   228  	kv1 := m.reservoir[m.allocCntr]
   229  	m.allocCntr++
   230  	kv2 := m.reservoir[m.allocCntr]
   231  	m.allocCntr++
   232  
   233  	for i := 0; i < len(nd.kv); i++ {
   234  		if m.less(nd.kv[i].key, splitkey) {
   235  			kv1 = append(kv1, nd.kv[i])
   236  		} else {
   237  			kv2 = append(kv2, nd.kv[i])
   238  		}
   239  	}
   240  
   241  	nd.min = sortedK[0]
   242  	nd.max = sortedK[halfIdx-1]
   243  	nd.kv = kv1
   244  
   245  	newNd := node{}
   246  	newNd.red = true
   247  	newNd.min = splitkey
   248  	newNd.max = sortedK[len(sortedK)-1]
   249  	newNd.kv = kv2
   250  
   251  	return &newNd
   252  
   253  }
   254  
   255  func isRed(nd *node) bool {
   256  	return nd != nil && nd.red
   257  }
   258  
   259  func colorFlip(nd *node) {
   260  	nd.red = !nd.red
   261  	if nd.left != nil {
   262  		nd.left.red = !nd.left.red
   263  	}
   264  	if nd.right != nil {
   265  		nd.right.red = !nd.right.red
   266  	}
   267  }
   268  
   269  func rotateLeft(root *node) *node {
   270  	x := root.right
   271  	root.right = x.left
   272  	x.left = root
   273  	x.red = root.red
   274  	root.red = true
   275  	return x
   276  }
   277  
   278  func rotateRight(root *node) *node {
   279  	x := root.left
   280  	root.left = x.right
   281  	x.right = root
   282  	x.red = root.red
   283  	root.red = true
   284  	return x
   285  }
   286  
   287  func do(nd *node, fct1 func(string, string)) {
   288  	if nd != nil {
   289  
   290  		do(nd.left, fct1)
   291  
   292  		for i := 0; i < len(nd.kv); i++ {
   293  			fct1(nd.kv[i].key, nd.kv[i].val)
   294  		}
   295  
   296  		do(nd.right, fct1)
   297  
   298  	}
   299  }
   300  
   301  // We do not provide an exported First() method because this is an
   302  // implementation detail.
   303  func first(root *node) *node {
   304  	for root.left != nil {
   305  		root = root.left
   306  	}
   307  	return root
   308  }
   309  
   310  func (m *OSMap) remove(root *node, key string) (*node, bool) {
   311  	deleted := false
   312  
   313  	/*
   314  		if m.less(key, root.key) {
   315  			if root.left != nil {
   316  				if !isRed(root.left) && !isRed(root.left.left) {
   317  					root = moveRedLeft(root)
   318  				}
   319  				root.left, deleted = m.remove(root.left, key)
   320  			}
   321  		} else {
   322  			if isRed(root.left) {
   323  				root = rotateRight(root)
   324  			}
   325  			if !m.less(key, root.key) && !m.less(root.key, key) &&
   326  				root.right == nil {
   327  				return nil, true
   328  			}
   329  			if root.right != nil {
   330  				if !isRed(root.right) && !isRed(root.right.left) {
   331  					root = moveRedRight(root)
   332  				}
   333  				if !m.less(key, root.key) && !m.less(root.key, key) {
   334  					smallest := first(root.right)
   335  					root.key = smallest.key
   336  					root.value = smallest.value
   337  					root.right = deleteMinimum(root.right)
   338  					deleted = true
   339  				} else {
   340  					root.right, deleted = m.remove(root.right, key)
   341  				}
   342  			}
   343  		}
   344  	*/
   345  	return fixUp(root), deleted
   346  }
   347  
   348  func moveRedLeft(root *node) *node {
   349  	colorFlip(root)
   350  	if root.right != nil && isRed(root.right.left) {
   351  		root.right = rotateRight(root.right)
   352  		root = rotateLeft(root)
   353  		colorFlip(root)
   354  	}
   355  	return root
   356  }
   357  
   358  func moveRedRight(root *node) *node {
   359  	colorFlip(root)
   360  	if root.left != nil && isRed(root.left.left) {
   361  		root = rotateRight(root)
   362  		colorFlip(root)
   363  	}
   364  	return root
   365  }
   366  
   367  func deleteMinimum(root *node) *node {
   368  	if root.left == nil {
   369  		return nil
   370  	}
   371  	if !isRed(root.left) && !isRed(root.left.left) {
   372  		root = moveRedLeft(root)
   373  	}
   374  	root.left = deleteMinimum(root.left)
   375  	return fixUp(root)
   376  }
   377  
   378  func fixUp(root *node) *node {
   379  	if isRed(root.right) {
   380  		root = rotateLeft(root)
   381  	}
   382  	if isRed(root.left) && isRed(root.left.left) {
   383  		root = rotateRight(root)
   384  	}
   385  	if isRed(root.left) && isRed(root.right) {
   386  		colorFlip(root)
   387  	}
   388  	return root
   389  }
   390  
   391  func printStatus(msg, key string, lvl int) {
   392  
   393  	if cntr%1000 < 20 {
   394  		kd := key
   395  		if len(key) > 3 {
   396  			kd = key[:3]
   397  		}
   398  		fmt.Printf("%-12v %5v l%2v\n", msg, kd, lvl)
   399  	}
   400  	cntr++
   401  }
   402  
   403  // is there a better way to convert a pointer to a hash
   404  func pointerHash(p *string) (int64, int) {
   405  
   406  	sp := fmt.Sprintf("%p", p) // string pointer
   407  
   408  	pi, err := strconv.ParseInt(sp, 0, 64) // pointer integer
   409  	if err != nil {
   410  		fmt.Printf("Error converting pointer to int64:  %v - pointer was %v\n", err, sp)
   411  		return 0, 0
   412  	}
   413  
   414  	mod := int(pi % (1000))
   415  
   416  	cntr++
   417  	if cntr%5000 == 0 {
   418  		fmt.Printf("%v %v | ", pi, mod)
   419  	}
   420  
   421  	return pi, mod
   422  
   423  }