TreeMap实现一致性hash

using System.Security.Cryptography;
using System.Text;

namespace ConsoleApp7
{
internal class Program
{
static void Main(string[] args)
{
var servers = new List
{
"192.168.1.2",
"192.168.1.3",
"192.168.1.4",
};

var consistentHash = new ConsistentHash<string, string>(100, servers,x => x.ToString());
var node = consistentHash.Get("2");

Console.WriteLine("Hello, World!");
}
}

public class ConsistentHash<K, V> where K : IComparable where V : IComparable
{
private readonly int vNodeCount;
private readonly TreeMap<long, V> circle;
private readonly IEnumerable nodes;
private readonly Func<V, string> keyGetter;

public ConsistentHash(int vNodeCount, IEnumerable nodes, Func<V, string> keyGetter)
{
this.vNodeCount = vNodeCount;
this.circle = new TreeMap<long, V>();
this.nodes = nodes;
this.keyGetter = keyGetter;
this.BuildTreeMap();
}

private void BuildTreeMap()
{
foreach (var node in nodes)
{
for (int i = 0; i < vNodeCount; i++)
{
var hashCode = HashKey(WrapKey(keyGetter(node), i));
circle.Put(hashCode, node);
}
}
}

public V Get(string key)
{
if (key == null) throw new ArgumentNullException(nameof(key));

var hashCode = HashKey(key);
var entry = circle.TailMap(hashCode).First();
return entry.Value;
}

private string WrapKey(string key, int index)
{
if (key == null) throw new ArgumentNullException(nameof(key));

return $"{key},{index}";
}

private long HashKey(string key)
{
if (key == null) throw new ArgumentNullException(nameof(key));

var bytes = MD5.HashData(Encoding.UTF8.GetBytes(key.ToString()!));

var hashCode = ((int)(bytes[3] & 0xFF) << 24)
| ((int)(bytes[2] & 0xFF) << 16)
| ((int)(bytes[1] & 0xFF) << 8)
| (bytes[0] & 0xFF);

return hashCode;
}

}

///


/// Map abstraction
///

/// Key data type
/// Value data type
public interface Map<K, V> : IEnumerable<KeyValuePair<K, V>> where K : IComparable where V : IComparable
{

///


/// Clears the map
///

void Clear();

///


/// Checks if the map contains key
///

/// key to look for
/// true if key exists, false otherwise
bool ContainsKey(K key);

///


/// Checks if the map contains value
///

/// value to look for
/// true if value exists, false otherwise
bool ContainsValue(V value);

///


/// Checks if the map is equal to given object
///

/// object to compare to
/// true if objects are equal
bool Equals(object o);

///


/// Gets the value associated with the given key
///

/// key to look for
/// value associated with the key
V Get(K key);

///


/// Checks if the map is empty or not
///

/// true if the map is empty, false otherwise
bool IsEmpty();

///


/// Gets all the keys contained in this map
///

/// List of keys
ICollection Keys();

///


/// Inserts (if key doesn't exist) or updates the value with the given key
///

/// key to insert or update
/// value to insert
/// newly inserted value
V Put(K key, V value);

///


/// Inserts all keys and values from the given map to this map
///

/// map with values to be inserted
void PutAll(Map<K, V> map);

///


/// Deletes an entry from the map
///

/// key to delete
/// deleted value
V Remove(K key);

///


/// Gets the number of entries in this map
///

/// number of entries
int Size();

///


/// Gets all the values contained in this map
///

/// List of values
ICollection Values();
}

///


/// Sorted map abstraction
///

/// Key data type
/// Value data type
interface SortedMap<K, V> : Map<K, V> where K : IComparable where V : IComparable
{

///


/// Returns the first key in this map
///

/// first key
K FirstKey();

///


/// Returns all entries that are strictly less than the specified key
///

/// key up to which to collect elements
/// map containing entries
SortedMap<K, V> HeadMap(K to);

///


/// Returns the last key in this map
///

/// last key
K LastKey();

///


/// Returns all entries from the map ranging from fromKey (inclusive) to toKey (exclusive)
///

///
///
/// map containing entries
SortedMap<K, V> SubMap(K fromKey, K toKey);

///


/// Returns all entries from the map that are greater or equal to the specified key
///

/// key to start collecting elements from
/// map containing elements
SortedMap<K, V> TailMap(K from);
}

///


/// TreeMap implementation
///

/// Key data type
/// Value data type
class TreeMap<K, V> : SortedMap<K, V> where K : IComparable where V : IComparable
{

// number of nodes in this tree
protected int Count { get; private set; }

// root node
protected Node<K, V> Root;

// comparator used to compare keys
protected IComparer Comparator;

///


/// Default class constructor. Automatically creates a comparator to use when comparing keys
///

public TreeMap()
{
Comparator = Comparer.Create((a, b) => a.CompareTo(b));
}

///


/// Class constructor. Sets the comparator to use when comparing keys to the specified one
///

/// comparator to use
public TreeMap(IComparer Comparator)
{
this.Comparator = Comparator;
}

///


/// Clears the map
///

public void Clear()
{
Root = null;
Count = 0;
}

///


/// Checks if the map contains specified key
///

/// key to look for
/// true if key exists, false otherwise
public bool ContainsKey(K key)
{
if (ReferenceEquals(key, null))
{
throw new ArgumentException("Key cannot be null at ContainsKey(K key)");
}

Node<K, V> node = Root;

while (!ReferenceEquals(node, null))
{
int compare = Comparator.Compare(key, node.Key);

if (compare < 0)
{
node = node.Left;
continue;
}
else if (compare > 0)
{
node = node.Right;
continue;
}

return true;
}

return false;
}

///


/// Checks if the map contains specified value
///

/// value to look for
/// true if the value exists, false otherwise
public bool ContainsValue(V value)
{
if (ReferenceEquals(value, null))
{
throw new ArgumentException("Value cannot be null at ContainsValue(V value)");
}

return ContainsValueRecursive(Root, value);
}

///


/// Helper method for ContainsValue(). Checks if the value exists starting from the specified node
///

/// node to start looking from
/// value to look for
/// true is the value exists in the sub-tree, false otherwise
private bool ContainsValueRecursive(Node<K, V> node, V value)
{
if (ReferenceEquals(node, null))
{
return false;
}

if (node.Value.CompareTo(value) == 0)
{
return true;
}

bool left = ContainsValueRecursive(node.Left, value);
bool right = ContainsValueRecursive(node.Right, value);

return left ? left : right;
}

///


/// Gets the first key in this map
///

/// first key
public K FirstKey()
{
Node<K, V> node = Root;

while (!ReferenceEquals(node, null))
{
if (ReferenceEquals(node.Left, null))
{
return node.Key;
}

node = node.Left;
}

return default(K);
}

///


/// Gets the value associated with the specified key
///

/// key to look for
/// value associated with the key, default value of V if not found
public V Get(K key)
{
if (ReferenceEquals(key, null))
{
throw new ArgumentException("Key cannot be null at Get(K key)");
}

Node<K, V> node = Root;

while (!ReferenceEquals(node, null))
{
int compare = Comparator.Compare(key, node.Key);

if (compare < 0)
{
node = node.Left;
continue;
}
else if (compare > 0)
{
node = node.Right;
continue;
}

return node.Value;
}

return default(V);
}

///


/// Gets all the elements that are strictly less than the specified key
///

/// key up to which elements will be added
/// map of elements
public SortedMap<K, V> HeadMap(K to)
{
if (ReferenceEquals(to, null))
{
throw new ArgumentException("Parameter to cannot be null at HeadMap(K to)");
}

TreeMap<K, V> map = new TreeMap<K, V>();

AddNodesRecursive(to, Root, map, false, true);

return map;
}

///


/// Checks if the map is empty or not
///

/// true if the map is empty, false if not
public bool IsEmpty()
{
return Count == 0;
}

///


/// Gets all keys stored in this map
///

/// collection of keys
public ICollection Keys()
{
List list = new List();

AddKeysRecursive(Root, list);

return list;
}

///


/// Helper method for Keys(). Adds all keys to the collection starting from specified node
///

/// node to start from
/// collection to add keys to
private void AddKeysRecursive(Node<K, V> node, ICollection collection)
{
if (ReferenceEquals(node, null))
{
return;
}

AddKeysRecursive(node.Left, collection);

collection.Add(node.Key);

AddKeysRecursive(node.Right, collection);
}

///


/// Gets the last key in this map
///

/// last key
public K LastKey()
{
Node<K, V> node = Root;

while (!ReferenceEquals(node, null))
{
if (ReferenceEquals(node.Right, null))
{
return node.Key;
}

node = node.Right;
}

return default(K);
}

///


/// Inserts (if key doesn't exist) or updates the value with the given key
///

/// key to insert or update
/// value to insert
/// newly inserted value
public V Put(K key, V value)
{
if (ReferenceEquals(key, null))
{
throw new ArgumentException("Key cannot be null at Put(K key, V value)");
}

Root = PutRecursive(key, value, Root);

return value;
}

///


/// Helper method for Put(). Recursively adds an element
///

/// key to put
/// value to put
/// node to put to
/// node with inserted value
private Node<K, V> PutRecursive(K key, V value, Node<K, V> node)
{
if (ReferenceEquals(node, null))
{
Count++;
return new Node<K, V>(key, value);
}

int comp = Comparator.Compare(key, node.Key);

if (comp < 0)
{
node.Left = PutRecursive(key, value, node.Left);

if (Height(node.Left) - Height(node.Right) == 2)
{
int comp2 = Comparator.Compare(key, node.Left.Key);
node = (comp2 < 0) ? RightRotation(node) : DoubleRightRotation(node);
}
}
else if (comp > 0)
{
node.Right = PutRecursive(key, value, node.Right);

if (Height(node.Right) - Height(node.Left) == 2)
{
int comp2 = Comparator.Compare(node.Right.Key, key);
node = (comp2 < 0) ? LeftRotation(node) : DoubleLeftRotation(node);
}
}
else
{
node.Value = value;
return node;
}

node.Height = Math.Max(Height(node.Left), Height(node.Right)) + 1;

return node;
}

///


/// Puts all elements found in the specified map to this map
///

/// map with elements to put
public void PutAll(Map<K, V> map)
{
foreach (KeyValuePair<K, V> x in map)
{
Put(x.Key, x.Value);
}
}

///


/// Removes the value associated with the specified key from the map
///

/// key to remove
/// removed value
public V Remove(K key)
{
if (ReferenceEquals(key, null))
{
throw new ArgumentException("Key cannot be null at Remove(K key)");
}

Node<K, V> removed = new Node<K, V>();

Root = RemoveRecursive(key, removed, Root);

return removed.Value;
}

///


/// Helper method for Remove(). Recursively removes an element
///

/// key to remove
/// removed node
/// node to start from
/// modified node
private Node<K, V> RemoveRecursive(K key, Node<K, V> removed, Node<K, V> node)
{
if (ReferenceEquals(node, null))
{
return null;
}

int compare = Comparator.Compare(key, node.Key);

if (compare < 0)
{
node.Left = RemoveRecursive(key, removed, node.Left);
}
else if (compare > 0)
{
node.Right = RemoveRecursive(key, removed, node.Right);
}
else if (node.Left != null && node.Right != null)
{
Node<K, V> maxNode = GetMax(node.Left);

removed.Key = node.Key;
removed.Value = node.Value;

node.Key = maxNode.Key;
node.Value = maxNode.Value;
node.Left = RemoveMax(node.Left);

Count--;
}
else
{
node = (node.Left != null) ? node.Left : node.Right;
Count--;
}

// re-balance the tree
if (ReferenceEquals(node, null))
{
return null;
}

node.Height = Math.Max(Height(node.Left), Height(node.Right)) + 1;

int balance = Height(node.Left) - Height(node.Right);

if (balance > 1 && Height(node.Left.Left) - Height(node.Left.Right) >= 0)
{
return RightRotation(node);
}

if (balance > 1 && Height(node.Left.Left) - Height(node.Left.Right) < 0)
{
node.Left = LeftRotation(node.Left);
return RightRotation(node);
}

if (balance < -1 && Height(node.Right.Left) - Height(node.Right.Right) <= 0)
{
return LeftRotation(node);
}

if (balance < -1 && Height(node.Right.Left) - Height(node.Right.Right) > 0)
{
node.Right = RightRotation(node.Right);
return LeftRotation(node);
}

return node;
}

///


/// Gets the number of elements in this map
///

/// number of elements
public int Size()
{
return Count;
}

///


/// Gets all emenents ranging from fromKey (inclusive) and toKey (exclusive)
///

/// key to start from
/// key to stop at
/// map of elements
public SortedMap<K, V> SubMap(K fromKey, K toKey)
{
if (ReferenceEquals(fromKey, null) || ReferenceEquals(toKey, null))
{
throw new ArgumentException("No parameter can be null at SubMap(K fromKey, K toKey)");
}

TreeMap<K, V> map = new TreeMap<K, V>();

AddNodesRecursiveSubMap(fromKey, toKey, Root, map);

return map;
}

///


/// Helper method for SubMap(). Recursively adds elements to the specified map
///

/// starting key
/// ending key
/// node to start from
/// map to add to
private void AddNodesRecursiveSubMap(K from, K to, Node<K, V> node, SortedMap<K, V> map)
{
if (ReferenceEquals(node, null))
{
return;
}

AddNodesRecursiveSubMap(from, to, node.Left, map);

int compare1 = Comparator.Compare(from, node.Key);
int compare2 = Comparator.Compare(to, node.Key);

if (compare1 <= 0 && compare2 > 0)
{
map.Put(node.Key, node.Value);
}

AddNodesRecursiveSubMap(from, to, node.Right, map);
}

///


/// Gets all elements that are greater of equal to the specified element
///

/// key to start from
/// map of elements
public SortedMap<K, V> TailMap(K from)
{
if (ReferenceEquals(from, null))
{
throw new ArgumentException("Parameter from cannot be null at TailMap(K from)");
}

TreeMap<K, V> map = new TreeMap<K, V>();

AddNodesRecursive(from, Root, map, true, false);

return map;
}

///


/// Helper method for TailMap() and HeadMap(). Adds elements to the specified map
///

/// comparison key
/// node to start from
/// map to add to
/// is the key inclusive
/// should it add lesser elements than the specified key
private void AddNodesRecursive(K key, Node<K, V> node, SortedMap<K, V> map, bool inclusive, bool lesser)
{
if (ReferenceEquals(node, null))
{
return;
}

AddNodesRecursive(key, node.Left, map, inclusive, lesser);

int compare = Comparator.Compare(key, node.Key);

if (compare < 0 && !lesser)
{
map.Put(node.Key, node.Value);
}
else if (compare > 0 && lesser)
{
map.Put(node.Key, node.Value);
}
else if (compare == 0 && inclusive)
{
map.Put(node.Key, node.Value);
}

AddNodesRecursive(key, node.Right, map, inclusive, lesser);
}

///


/// Gets all the values stored in this map
///

/// collection of values
public ICollection Values()
{
List list = new List();

AddValuesRecursive(Root, list);

return list;
}

///


/// Helper method for Values(). Recursively adds values to a collection starting from the specified node
///

/// node to start from
/// collection to add to
private void AddValuesRecursive(Node<K, V> node, ICollection collection)
{
if (ReferenceEquals(node, null))
{
return;
}

AddValuesRecursive(node.Left, collection);

collection.Add(node.Value);

AddValuesRecursive(node.Right, collection);
}

///


/// Removes the greatest element from a sub-tree
///

/// root node of the sub-tree
/// modified node
protected Node<K, V> RemoveMax(Node<K, V> node)
{
if (ReferenceEquals(node, null))
{
return null;
}
else if (node.Right != null)
{
node.Right = RemoveMax(node.Right);
return node;
}
else
{
return node.Left;
}
}

///


/// Gets the greatest element in a sub-tree
///

/// root node of the sub-tree
/// greatest element
protected Node<K, V> GetMax(Node<K, V> node)
{
Node<K, V> parent = null;

while (!ReferenceEquals(node, null))
{
parent = node;
node = node.Right;
}

return parent;
}

// ************* TREE TORATIONS ************* //
protected Node<K, V> RightRotation(Node<K, V> n2)
{
Node<K, V> n1 = n2.Left;

n2.Left = n1.Right;
n1.Right = n2;

n2.Height = Math.Max(Height(n2.Left), Height(n2.Right)) + 1;
n1.Height = Math.Max(Height(n1.Left), Height(n2)) + 1;

return n1;
}

protected Node<K, V> LeftRotation(Node<K, V> n1)
{
Node<K, V> n2 = n1.Right;

n1.Right = n2.Left;
n2.Left = n1;

n1.Height = Math.Max(Height(n1.Left), Height(n1.Right)) + 1;
n2.Height = Math.Max(Height(n2.Right), Height(n1)) + 1;

return n2;
}

protected Node<K, V> DoubleRightRotation(Node<K, V> n3)
{
n3.Left = LeftRotation(n3.Left);

return RightRotation(n3);
}

protected Node<K, V> DoubleLeftRotation(Node<K, V> n1)
{
n1.Right = RightRotation(n1.Right);

return LeftRotation(n1);
}

protected int Height(Node<K, V> node)
{
return ReferenceEquals(node, null) ? -1 : node.Height;
}
// ************* END OF TREE TORATIONS ************* //

// ************ ITERATION LOGIC ************ //
public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
{
List<KeyValuePair<K, V>> nodes = new List<KeyValuePair<K, V>>();

AddNodesRecursive(Root, nodes);

foreach (KeyValuePair<K, V> node in nodes)
{
yield return node;
}
}

private void AddNodesRecursive(Node<K, V> node, ICollection<KeyValuePair<K, V>> collection)
{
if (ReferenceEquals(node, null))
{
return;
}

AddNodesRecursive(node.Left, collection);

collection.Add(new KeyValuePair<K, V>(node.Key, node.Value));

AddNodesRecursive(node.Right, collection);
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

// ************ END OF ITERATION LOGIC ************ //

///


/// Tree node class containing key, value, height of the node, left and right nodes
///

/// Key data type
/// Value data type
protected class Node<K, V>
{

public K Key { get; set; }
public V Value { get; set; }

public Node<K, V> Left { get; set; }
public Node<K, V> Right { get; set; }

public int Height { get; set; }

public Node() { }

public Node(K Key, V Value) : this(Key, Value, null, null) { }

public Node(K Key, V Value, Node<K, V> Left, Node<K, V> Right)
{
this.Key = Key;
this.Value = Value;
this.Left = Left;
this.Right = Right;
}
}
}
}

posted @ 2024-09-26 16:09  pojianbing  阅读(36)  评论(0)    收藏  举报