Skip to content

Commit

Permalink
Added key/value support to Ternary Search Trees.
Browse files Browse the repository at this point in the history
  • Loading branch information
SuprDewd committed Aug 11, 2011
1 parent 8170df4 commit 497b946
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 119 deletions.
64 changes: 34 additions & 30 deletions SharpBag/Collections/TernarySearchTree.cs
Expand Up @@ -11,11 +11,13 @@ namespace SharpBag.Collections
/// A ternary search tree.
/// </summary>
/// <typeparam name="T">The type of items in the tree.</typeparam>
public class TernarySearchTree<T> : IEnumerable<T[]> where T : IComparable<T>
public class TernarySearchTree<T, V> : IEnumerable<KeyValuePair<T[], V>> where T : IComparable<T>
{
private class Node
{
public T Value { get; private set; }
public T Key { get; private set; }

public V Value { get; set; }

public bool IsEnd { get; set; }

Expand All @@ -25,15 +27,15 @@ private class Node

public Node Right { get; set; }

public Node(T value)
public Node(T key)
{
this.Value = value;
this.Key = key;
this.IsEnd = false;
}

public Node GetNextFor(T value)
{
return this.GetNextFor(this.Value.CompareTo(value));
return this.GetNextFor(this.Key.CompareTo(value));
}

public Node GetNextFor(int cmp)
Expand All @@ -45,7 +47,7 @@ public Node GetNextFor(int cmp)

public void Add(Node node)
{
this.Add(node, this.Value.CompareTo(node.Value));
this.Add(node, this.Key.CompareTo(node.Key));
}

public void Add(Node node, int cmp)
Expand All @@ -64,7 +66,7 @@ public void Add(Node node, int cmp)
/// <summary>
/// Gets the items.
/// </summary>
public IEnumerable<T[]> Items
public IEnumerable<KeyValuePair<T[], V>> Items
{
get
{
Expand All @@ -85,31 +87,32 @@ public IEnumerable<T[]> Items
/// <summary>
/// Adds the specified sequence.
/// </summary>
/// <param name="sequence">The sequence.</param>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
/// <returns>Whether the sequence was new.</returns>
public virtual bool Add(T[] sequence)
public virtual bool Add(T[] key, V value)
{
Contract.Requires(sequence.Length > 0);
Contract.Requires(key.Length > 0);
bool isNew = false;

if (this.Root == null)
{
this.Root = new Node(sequence[0]);
this.Root = new Node(key[0]);
isNew = true;
}

Node cur = this.Root;
for (int i = 0; i < sequence.Length; i++)
for (int i = 0; i < key.Length; i++)
{
int cmp = cur.Value.CompareTo(sequence[i]);
int cmp = cur.Key.CompareTo(key[i]);

if (cmp == 0)
{
if (i < sequence.Length - 1)
if (i < key.Length - 1)
{
if (cur.Below == null)
{
cur.Below = new Node(sequence[i + 1]);
cur.Below = new Node(key[i + 1]);
isNew = true;
}

Expand All @@ -120,7 +123,7 @@ public virtual bool Add(T[] sequence)
{
if (cur.Left == null)
{
cur.Left = new Node(sequence[i]);
cur.Left = new Node(key[i]);
isNew = true;
}

Expand All @@ -131,18 +134,19 @@ public virtual bool Add(T[] sequence)
{
if (cur.Right == null)
{
cur.Right = new Node(sequence[i]);
cur.Right = new Node(key[i]);
isNew = true;
}

cur = cur.Right;
i--;
}

if (i + 1 == sequence.Length)
if (i + 1 == key.Length)
{
if (!cur.IsEnd) isNew = true;
cur.IsEnd = true;
cur.Value = value;
}
}

Expand All @@ -165,7 +169,7 @@ public virtual bool Contains(T[] sequence)
Node cur = this.Root;
for (int i = 0; i < sequence.Length; i++)
{
int cmp = cur.Value.CompareTo(sequence[i]);
int cmp = cur.Key.CompareTo(sequence[i]);
if (i == sequence.Length - 1 && cmp == 0) return cur.IsEnd;
cur = cur.GetNextFor(cmp);
if (cmp != 0) i--;
Expand All @@ -180,42 +184,42 @@ public virtual bool Contains(T[] sequence)
/// </summary>
/// <param name="sequence">The sequence of starting elements.</param>
/// <returns>The sequences starting with the specified elements.</returns>
public virtual IEnumerable<T[]> StartingWith(T[] sequence)
public virtual IEnumerable<KeyValuePair<T[], V>> StartingWith(T[] sequence)
{
Contract.Requires(sequence.Length > 0);
if (this.Root == null) yield break;

Node cur = this.Root;
for (int i = 0; i < sequence.Length; i++)
{
int cmp = cur.Value.CompareTo(sequence[i]);
int cmp = cur.Key.CompareTo(sequence[i]);
if (i == sequence.Length - 1 && cmp == 0) break;
cur = cur.GetNextFor(cmp);
if (cmp != 0) i--;
if (cur == null) yield break;
}

if (cur.IsEnd) yield return sequence;
if (cur.Below != null) foreach (T[] seq in this.StartingWith(sequence, cur.Below)) yield return seq;
if (cur.IsEnd) yield return new KeyValuePair<T[], V>(sequence, cur.Value);
if (cur.Below != null) foreach (KeyValuePair<T[], V> seq in this.StartingWith(sequence, cur.Below)) yield return seq;
}

private IEnumerable<T[]> StartingWith(T[] sequence, Node cur)
private IEnumerable<KeyValuePair<T[], V>> StartingWith(T[] sequence, Node cur)
{
T[] seq = new T[sequence.Length + 1];
Array.Copy(sequence, seq, sequence.Length);
seq[sequence.Length] = cur.Value;
seq[sequence.Length] = cur.Key;

if (cur.IsEnd) yield return seq;
if (cur.Left != null) foreach (T[] s in this.StartingWith(sequence, cur.Left)) yield return s;
if (cur.Below != null) foreach (T[] s in this.StartingWith(seq, cur.Below)) yield return s;
if (cur.Right != null) foreach (T[] s in this.StartingWith(sequence, cur.Right)) yield return s;
if (cur.IsEnd) yield return new KeyValuePair<T[], V>(seq, cur.Value);
if (cur.Left != null) foreach (KeyValuePair<T[], V> s in this.StartingWith(sequence, cur.Left)) yield return s;
if (cur.Below != null) foreach (KeyValuePair<T[], V> s in this.StartingWith(seq, cur.Below)) yield return s;
if (cur.Right != null) foreach (KeyValuePair<T[], V> s in this.StartingWith(sequence, cur.Right)) yield return s;
}

/// <summary>
/// Gets the enumerator.
/// </summary>
/// <returns>The enumerator.</returns>
public IEnumerator<T[]> GetEnumerator()
public IEnumerator<KeyValuePair<T[], V>> GetEnumerator()
{
foreach (var item in this.Items)
{
Expand Down
54 changes: 28 additions & 26 deletions SharpBag/Collections/TernaryStringSearchTree.cs
Expand Up @@ -9,7 +9,7 @@ namespace SharpBag.Collections
/// <summary>
/// A ternary string-search tree.
/// </summary>
public class TernaryStringSearchTree : TernarySearchTree<char>, IEnumerable<string>
public class TernaryStringSearchTree<V> : TernarySearchTree<char, V>, IEnumerable<KeyValuePair<string, V>>
{
/// <summary>
/// Gets a value indicating whether the search tree is case sensitive.
Expand All @@ -22,13 +22,13 @@ public class TernaryStringSearchTree : TernarySearchTree<char>, IEnumerable<stri
/// <summary>
/// Gets the items.
/// </summary>
public new IEnumerable<string> Items
public new IEnumerable<KeyValuePair<string, V>> Items
{
get
{
foreach (var item in base.Items)
{
yield return new String(item);
yield return new KeyValuePair<string, V>(new String(item.Key), item.Value);
}
}
}
Expand All @@ -50,74 +50,76 @@ private char[] ToUpper(char[] sequence)
}

/// <summary>
/// Adds the specified sequence.
/// Adds the specified key and value.
/// </summary>
/// <param name="sequence">The sequence.</param>
/// <returns>Whether the sequence was new.</returns>
public bool Add(string sequence)
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
/// <returns>Whether the key was new.</returns>
public bool Add(string key, V value)
{
return base.Add(this.CaseSensitive ? sequence.ToCharArray() : this.ToUpper(sequence.ToCharArray()));
return this.Add(key.ToCharArray(), value);
}

/// <summary>
/// Adds the specified sequence.
/// Adds the specified key and value.
/// </summary>
/// <param name="sequence">The sequence.</param>
/// <returns>Whether the sequence was new.</returns>
public override bool Add(char[] sequence)
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
/// <returns>Whether the key was new.</returns>
public override bool Add(char[] key, V value)
{
return base.Add(this.CaseSensitive ? sequence : this.ToUpper(sequence));
return base.Add(this.CaseSensitive ? key : this.ToUpper(key), value);
}

/// <summary>
/// Determines whether the current instance contains the specified sequence.
/// </summary>
/// <param name="sequence">The sequence.</param>
/// <param name="key">The key.</param>
/// <returns>
/// <c>true</c> if the current instance contains the specified sequence; otherwise, <c>false</c>.
/// </returns>
public bool Contains(string sequence)
public bool Contains(string key)
{
return base.Contains(this.CaseSensitive ? sequence.ToCharArray() : this.ToUpper(sequence.ToCharArray()));
return this.Contains(key.ToCharArray());
}

/// <summary>
/// Determines whether the current instance contains the specified sequence.
/// </summary>
/// <param name="sequence">The sequence.</param>
/// <param name="key">The key.</param>
/// <returns>
/// <c>true</c> if the current instance contains the specified sequence; otherwise, <c>false</c>.
/// </returns>
public override bool Contains(char[] sequence)
public override bool Contains(char[] key)
{
return base.Contains(this.CaseSensitive ? sequence : this.ToUpper(sequence));
return base.Contains(this.CaseSensitive ? key : this.ToUpper(key));
}

/// <summary>
/// Gets all the sequences starting with the specified sequence.
/// </summary>
/// <param name="sequence">The sequence of starting elements.</param>
/// <param name="key">The sequence of starting elements.</param>
/// <returns>The sequences starting with the specified sequence.</returns>
public IEnumerable<string> StartingWith(string sequence)
public IEnumerable<KeyValuePair<string, V>> StartingWith(string key)
{
return base.StartingWith(this.CaseSensitive ? sequence.ToCharArray() : this.ToUpper(sequence.ToCharArray())).Select(i => new String(i));
return this.StartingWith(key.ToCharArray());
}

/// <summary>
/// Gets all the sequences starting with the specified sequence.
/// </summary>
/// <param name="sequence">The sequence of starting elements.</param>
/// <param name="key">The sequence of starting elements.</param>
/// <returns>The sequences starting with the specified sequence.</returns>
public new IEnumerable<string> StartingWith(char[] sequence)
public new IEnumerable<KeyValuePair<string, V>> StartingWith(char[] key)
{
return base.StartingWith(this.CaseSensitive ? sequence : this.ToUpper(sequence)).Select(i => new String(i));
return base.StartingWith(this.CaseSensitive ? key : this.ToUpper(key)).Select(i => new KeyValuePair<string, V>(new String(i.Key), i.Value));
}

/// <summary>
/// Gets the enumerator.
/// </summary>
/// <returns>The enumerator.</returns>
public new IEnumerator<string> GetEnumerator()
public new IEnumerator<KeyValuePair<string, V>> GetEnumerator()
{
foreach (var item in this.Items)
{
Expand Down
Binary file modified SharpBag/bin/Release/CodeContracts/SharpBag.Contracts.dll
Binary file not shown.
Binary file modified SharpBag/bin/Release/SharpBag.dll
Binary file not shown.

0 comments on commit 497b946

Please sign in to comment.