github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/omap/osmap/osmap.go (about)

     1  package osmap
     2  
     3  // OSMap is a ordered string keyed map.
     4  // It is eight to ten times slower than golang builtin map.
     5  // Confirming my rule of thumb for hash-based vs. btree-based structures.
     6  
     7  type OSMap struct {
     8  	root   *node
     9  	less   func(string, string) bool
    10  	length int
    11  }
    12  
    13  type node struct {
    14  	key, value  string
    15  	red         bool
    16  	left, right *node
    17  }
    18  
    19  // New returns an empty Map
    20  func New() *OSMap {
    21  	f := func(a, b string) bool {
    22  		return a < b
    23  	}
    24  	return &OSMap{less: f}
    25  }
    26  
    27  // Insert inserts a new key-value into the Map returning true;
    28  // or replaces an existing key-value pair's value returning false.
    29  //      inserted := myMap.Insert(key, value).
    30  func (m *OSMap) Insert(key, value string) (inserted bool) {
    31  	m.root, inserted = m.insert(m.root, key, value, 0)
    32  	m.root.red = false
    33  	if inserted {
    34  		m.length++
    35  	}
    36  	return inserted
    37  }
    38  
    39  // For compatibility
    40  func (m *OSMap) Set(key, value string) (inserted bool) { return m.Insert(key, value) }
    41  
    42  // Find returns the value and true if the key is in the Map
    43  // or nil and false otherwise.
    44  //      value, found := myMap.Find(key).
    45  func (m *OSMap) Find(key string) (value string, found bool) {
    46  	root := m.root
    47  	for root != nil {
    48  		if m.less(key, root.key) {
    49  			root = root.left
    50  		} else if m.less(root.key, key) {
    51  			root = root.right
    52  		} else {
    53  			return root.value, true
    54  		}
    55  	}
    56  	return "", false // string null value
    57  }
    58  
    59  // For compatibility
    60  func (m *OSMap) Get(key string) (value string, found bool) { return m.Find(key) }
    61  
    62  // Delete deletes the key-value returning true,
    63  // or does nothing returning false
    64  //      deleted := myMap.Delete(key).
    65  func (m *OSMap) Delete(key string) (deleted bool) {
    66  	if m.root != nil {
    67  		if m.root, deleted = m.remove(m.root, key); m.root != nil {
    68  			m.root.red = false
    69  		}
    70  	}
    71  	if deleted {
    72  		m.length--
    73  	}
    74  	return deleted
    75  }
    76  
    77  // Do calls the given function on every key-value in the Map in order.
    78  func (m *OSMap) Do(function func(string, string)) {
    79  	do(m.root, function)
    80  }
    81  
    82  // Len returns the number of key-value pairs in the map.
    83  func (m *OSMap) Len() int {
    84  	return m.length
    85  }
    86  
    87  // ========================================================
    88  func INNER_CORE_FOR_EXTRACTION() {
    89  	// insert(args)
    90  	// do(args)
    91  	// remove(args)
    92  
    93  }
    94  
    95  func (m *OSMap) insert(root *node, key, value string, lvl int) (*node, bool) {
    96  	inserted := false
    97  	if root == nil { // If the key was in the tree it would belong here
    98  		if m.length%1000 == 0 && m.length > 10 {
    99  			// fmt.Printf("l%v-%v - ", lvl, m.length)
   100  		}
   101  		return &node{key: key, value: value, red: true}, true
   102  	}
   103  	if isRed(root.left) && isRed(root.right) {
   104  		colorFlip(root)
   105  	}
   106  	if m.less(key, root.key) {
   107  		root.left, inserted = m.insert(root.left, key, value, lvl+1)
   108  	} else if m.less(root.key, key) {
   109  		root.right, inserted = m.insert(root.right, key, value, lvl+1)
   110  	} else { // The key is already in the tree so just replace its value
   111  		root.value = value
   112  	}
   113  	if isRed(root.right) && !isRed(root.left) {
   114  		root = rotateLeft(root)
   115  	}
   116  	if isRed(root.left) && isRed(root.left.left) {
   117  		root = rotateRight(root)
   118  	}
   119  	return root, inserted
   120  }
   121  
   122  func isRed(root *node) bool {
   123  	return root != nil && root.red
   124  }
   125  
   126  func colorFlip(root *node) {
   127  	root.red = !root.red
   128  	if root.left != nil {
   129  		root.left.red = !root.left.red
   130  	}
   131  	if root.right != nil {
   132  		root.right.red = !root.right.red
   133  	}
   134  }
   135  
   136  func rotateLeft(root *node) *node {
   137  	x := root.right
   138  	root.right = x.left
   139  	x.left = root
   140  	x.red = root.red
   141  	root.red = true
   142  	return x
   143  }
   144  
   145  func rotateRight(root *node) *node {
   146  	x := root.left
   147  	root.left = x.right
   148  	x.right = root
   149  	x.red = root.red
   150  	root.red = true
   151  	return x
   152  }
   153  
   154  func do(root *node, function func(string, string)) {
   155  	if root != nil {
   156  		do(root.left, function)
   157  		function(root.key, root.value)
   158  		do(root.right, function)
   159  	}
   160  }
   161  
   162  // We do not provide an exported First() method because this is an
   163  // implementation detail.
   164  func first(root *node) *node {
   165  	for root.left != nil {
   166  		root = root.left
   167  	}
   168  	return root
   169  }
   170  
   171  func (m *OSMap) remove(root *node, key string) (*node, bool) {
   172  	deleted := false
   173  	if m.less(key, root.key) {
   174  		if root.left != nil {
   175  			if !isRed(root.left) && !isRed(root.left.left) {
   176  				root = moveRedLeft(root)
   177  			}
   178  			root.left, deleted = m.remove(root.left, key)
   179  		}
   180  	} else {
   181  		if isRed(root.left) {
   182  			root = rotateRight(root)
   183  		}
   184  		if !m.less(key, root.key) && !m.less(root.key, key) &&
   185  			root.right == nil {
   186  			return nil, true
   187  		}
   188  		if root.right != nil {
   189  			if !isRed(root.right) && !isRed(root.right.left) {
   190  				root = moveRedRight(root)
   191  			}
   192  			if !m.less(key, root.key) && !m.less(root.key, key) {
   193  				smallest := first(root.right)
   194  				root.key = smallest.key
   195  				root.value = smallest.value
   196  				root.right = deleteMinimum(root.right)
   197  				deleted = true
   198  			} else {
   199  				root.right, deleted = m.remove(root.right, key)
   200  			}
   201  		}
   202  	}
   203  	return fixUp(root), deleted
   204  }
   205  
   206  func moveRedLeft(root *node) *node {
   207  	colorFlip(root)
   208  	if root.right != nil && isRed(root.right.left) {
   209  		root.right = rotateRight(root.right)
   210  		root = rotateLeft(root)
   211  		colorFlip(root)
   212  	}
   213  	return root
   214  }
   215  
   216  func moveRedRight(root *node) *node {
   217  	colorFlip(root)
   218  	if root.left != nil && isRed(root.left.left) {
   219  		root = rotateRight(root)
   220  		colorFlip(root)
   221  	}
   222  	return root
   223  }
   224  
   225  func deleteMinimum(root *node) *node {
   226  	if root.left == nil {
   227  		return nil
   228  	}
   229  	if !isRed(root.left) && !isRed(root.left.left) {
   230  		root = moveRedLeft(root)
   231  	}
   232  	root.left = deleteMinimum(root.left)
   233  	return fixUp(root)
   234  }
   235  
   236  func fixUp(root *node) *node {
   237  	if isRed(root.right) {
   238  		root = rotateLeft(root)
   239  	}
   240  	if isRed(root.left) && isRed(root.left.left) {
   241  		root = rotateRight(root)
   242  	}
   243  	if isRed(root.left) && isRed(root.right) {
   244  		colorFlip(root)
   245  	}
   246  	return root
   247  }