基于红黑树实现集合
class RBT1Set<E> : ISet<E> where E : IComparable<E>
{
private RBT1<E> rbt;
public RBT1Set()
{
rbt = new RBT1<E>();
}
public int Count { get { return rbt.Count; } }
public bool IsEmpty { get { return rbt.IsEmpty; } }
public void Add(E e)
{
rbt.Add(e);
}
public bool Contains(E e)
{
return rbt.Contains(e);
}
public void Remove(E e)
{
Console.WriteLine("待实现");
}
public int MaxHeigh()
{
return rbt.MaxHeigh();
}
}
与基于二叉查找树实现的集合对比测试:
class Program
{
private static long TestSet(ISet<string> set, List<string> words)
{
Stopwatch t = new Stopwatch();
t.Start();
foreach (string word in words)
set.Add(word);
t.Stop();
return t.ElapsedMilliseconds;
}
static void Main(string[] args)
{
Console.WriteLine("双城记");
List<string> words = TestHelper.ReadFile("测试文件1/双城记.txt");
Console.WriteLine("词汇量总数:" + words.Count);
Console.WriteLine();
Console.WriteLine("(基于二叉查找树实现)集合");
BST1Set<string> bst1Set = new BST1Set<string>();
long t1 = TestSet(bst1Set, words);
Console.WriteLine("不同单词的总数: " + bst1Set.Count);
Console.WriteLine("运行时间: " + t1 + "ms");
Console.WriteLine("树的最大高度: " + bst1Set.MaxHeight());
Console.WriteLine();
Console.WriteLine("(基于红黑树实现)集合");
RBT1Set<string> rbt1Set = new RBT1Set<string>();
long t2 = TestSet(rbt1Set, words);
Console.WriteLine("不同单词的总数: " + rbt1Set.Count);
Console.WriteLine("运行时间: " + t2 + "ms");
Console.WriteLine("树的最大高度: " + rbt1Set.MaxHeight());
Console.Read();
}
}
测试1000万个数顺序插入红黑树集合:
class Program
{
static void Main(string[] args)
{
Stopwatch t = new Stopwatch();
t.Start();
RBT1Set<int> set = new RBT1Set<int>();
for (int i = 0; i < 10000000; i++)
set.Add(i);
t.Stop();
Console.WriteLine("运行时间:" + t.ElapsedMilliseconds + "ms");
Console.WriteLine("数的最大高度:"+ set.MaxHeight());
Console.Read();
}
}
基于红黑树实现映射
映射底层红黑树代码:
class RBT2<Key,Value> where Key : IComparable<Key>
{
private const bool Red = true;
private const bool Black = false;
private class Node
{
public Key key;
public Value value;
public Node left;
public Node right;
public bool color;
public Node(Key key,Value value)
{
this.key = key;
this.value = value;
left = null;
right = null;
color = Red;
}
}
private Node root;
private int N;
public RBT2()
{
root = null;
N = 0;
}
public int Count { get { return N; } }
public bool IsEmpty { get { return N == 0; } }
private bool IsRed(Node node)
{
if (node == null)
return Black;
return node.color;
}
// node x
// / \ 左旋转 / \
// T1 x ---------> node T3
// / \ / \
// T2 T3 T1 T2
//返回左旋转后新的二叉查找树的根
private Node LeftRotate(Node node)
{
Node x = node.right;
node.right = x.left;
x.left = node;
x.color = node.color;
node.color = Red; //node.color对应2-3树中的3节点,所以一定是红色的
return x;
}
private void FlipColors(Node node)
{
node.color = Red;
node.left.color = Black;
node.right.color = Black;
}
// node x
// / \ 右旋转 / \
// x T2 -------> T3 node
// / \ / \
// T3 T1 T1 T2
//返回右旋转后新的二叉查找树的根,对新的二叉查找树进行后续的修复操作
//右旋转过程中保证二叉树的性质,左子树都比根节点小,右子树都比根节点大
private Node RightRotate(Node node)
{
Node x = node.left;
node.left = x.right;
x.right = node;
x.color = node.color;
node.color = Red;
return x;
}
//往红黑树中添加元素,递归实现
public void Add(Key key,Value value)
{
root = Add(root, key,value);
root.color = Black;
}
//以node为根的树中添加元素e,添加后返回根节点node
private Node Add(Node node, Key key,Value value)
{
if (node == null)
{
N++;
return new Node(key,value); //默认为红结点
}
if (key.CompareTo(node.key) < 0)
node.left = Add(node.left, key, value);
else if (key.CompareTo(node.key) > 0)
node.right = Add(node.right, key, value);
else //key.CompareTo(node.key) = 0
node.value = value;
//如果出现右子结点是红色,而左子结点是黑色,进行左旋转
if (IsRed(node.right) && !IsRed(node.left))
node = LeftRotate(node);
//如果出现连续的左子节点都是红色,进行右旋转
if (IsRed(node.left) && IsRed(node.left.left))
node = RightRotate(node);
//如果出现左右子节点均为红色,进行颜色反转
if (IsRed(node.left) && IsRed(node.right))
FlipColors(node);
return node;
}
private Node GetNode(Node node, Key key)
{
if (node == null)
return null;
if (key.Equals(node.key))
return node;
else if (key.CompareTo(node.key) < 0)
return GetNode(node.left, key);
else //key.CompareTo(node.key) > 0
return GetNode(node.right, key);
}
public bool Contains(Key key)
{
return GetNode(root, key) != null;
}
public Value Get(Key key)
{
Node node = GetNode(root, key);
if (node == null)
throw new ArgumentException("键" + key + "不存在,无法获取对应值!");
else
return node.value;
}
public void Set(Key key, Value newValue)
{
Node node = GetNode(root, key);
if (node == null)
throw new ArgumentException("键" + key + "不存在,无法更改对应值!");
else
node.value = newValue;
}
}
基于红黑树实现映射:
class RBT2Dictionary<Key, Value> : IDictionary<Key, Value> where Key : IComparable<Key>
{
private RBT2<Key, Value> rbt;
public RBT2Dictionary()
{
rbt = new RBT2<Key, Value>();
}
public int Count { get { return rbt.Count; } }
public bool IsEmpty { get { return rbt.IsEmpty; } }
public void Add(Key key, Value value)
{
rbt.Add(key, value);
}
public bool ContainsKey(Key key)
{
return rbt.Contains(key);
}
public Value Get(Key key)
{
return rbt.Get(key);
}
public void Remove(Key key)
{
Console.WriteLine("待实现");
}
public void Set(Key key, Value newValue)
{
rbt.Set(key, newValue);
}
}
基于二叉查找树与红黑树实现的字典对比测试:
class Program
{
public static long TestDictionary(IDictionary<string, int> dic, List<string> words)
{
Stopwatch t = new Stopwatch();
t.Start();
foreach (var word in words)
{
//如果单词不存在字典中,说明是第一次遇见这个单词,频次设为1
if (!dic.ContainsKey(word))
dic.Add(word, 1);
else //如果单词已经存在在字典中,将单词对应的频次+1
dic.Set(word, dic.Get(word) + 1);
}
t.Stop();
return t.ElapsedMilliseconds;
}
static void Main(string[] args)
{
Console.WriteLine("双城记");
List<string> words = TestHelper.ReadFile("测试文件1/双城记.txt");
Console.WriteLine("词汇量总数:" + words.Count);
Console.WriteLine();
Console.WriteLine("(基于二叉查找树实现)字典");
BST2Dictionary<string, int> dic1 = new BST2Dictionary<string, int>();
long t1 = TestDictionary(dic1, words);
Console.WriteLine("不同的单词总数: " + dic1.Count);
Console.WriteLine("city出现的频次: " + dic1.Get("city"));
Console.WriteLine("运行时间: " + t1 + "ms");
Console.WriteLine();
Console.WriteLine("(基于红黑树实现)字典");
RBT2Dictionary<string, int> dic2 = new RBT2Dictionary<string, int>();
long t2 = TestDictionary(dic2, words);
Console.WriteLine("不同的单词总数: " + dic2.Count);
Console.WriteLine("city出现的频次: " + dic2.Get("city"));
Console.WriteLine("运行时间: " + t2 + "ms");
Console.Read();
}
}