37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Runtime.InteropServices;
40 using System.Diagnostics;
42 namespace Com.Mission_Base.Pbl
56 [DebuggerDisplay(
"Count = {Count}")]
57 public class AvlDictionary<TKey, TValue> :
58 IDictionary<TKey, TValue>,
60 where TKey : IComparable<TKey>
65 public class AvlDictionaryBaseEnumerator
68 private AvlTreeNode _node;
69 private bool _isExhausted;
70 private readonly
long _changeCounter;
81 _avlDictionary = dictionary;
82 _changeCounter = dictionary._changeCounter;
84 _isExhausted = _avlDictionary._rootNode == null;
94 protected bool IsPositioned
96 get {
return !_isExhausted && null != _node; }
106 protected KeyValuePair<TKey, TValue> CurrentPair
110 if (!_isExhausted && null != _node)
114 return new KeyValuePair<TKey, TValue>(
default(TKey),
default(TValue));
125 protected TKey CurrentKey
129 if (!_isExhausted && null != _node)
131 return _node.Pair.Key;
133 return default(TKey);
144 protected TValue CurrentValue
148 if (!_isExhausted && null != _node)
150 return _node.Pair.Value;
152 return default(TValue);
166 public bool MoveNext()
168 if (_changeCounter != _avlDictionary._changeCounter)
170 throw new InvalidOperationException(
"The AvlDictionary was modified after the enumerator was created.");
176 if (null == _avlDictionary._rootNode)
182 AvlTreeNode next = null == _node ? _avlDictionary._rootNode.PblTreeNodeFirst() : _node.PblTreeNodeNext();
200 _isExhausted = _avlDictionary._rootNode == null;
203 #region IDisposable Member
209 public void Dispose()
219 public sealed
class Enumerator : AvlDictionaryBaseEnumerator, IEnumerator<KeyValuePair<TKey, TValue>>
233 #region IEnumerator<KeyValuePair<TKey,TValue>> Member
242 public KeyValuePair<TKey, TValue> Current
244 get {
return CurrentPair; }
249 #region IEnumerator Member
261 object IEnumerator.Current
267 throw new InvalidOperationException(
"The enumerator is not positioned.");
280 private sealed
class AvlTreeNode
282 internal KeyValuePair<TKey, TValue> Pair;
283 internal AvlTreeNode Prev;
284 internal AvlTreeNode Next;
285 internal AvlTreeNode Parent;
286 private int _balance;
288 private AvlTreeNode(KeyValuePair<TKey, TValue> pair)
302 internal AvlTreeNode PblTreeNodeFirst()
304 AvlTreeNode node =
this;
305 while (node.Prev != null)
317 internal AvlTreeNode PblTreeNodeNext()
319 AvlTreeNode node =
this;
320 if (node.Next != null)
322 return node.Next.PblTreeNodeFirst();
326 AvlTreeNode child = node;
328 while ((node = node.Parent) != null)
330 if (child == node.Prev)
344 private void PblAvlTreeSetLeft(AvlTreeNode referenceNode)
346 if (Prev != referenceNode)
348 if ((Prev = referenceNode) != null) { Prev.Parent =
this; }
352 private void PblAvlTreeSetRight(AvlTreeNode referenceNode)
354 if (Next != referenceNode)
356 if ((Next = referenceNode) != null) { Next.Parent =
this; }
369 static internal AvlTreeNode PblTreeNodeInsert(
370 AvlTreeNode parentNode,
373 out
int heightChanged,
374 out AvlTreeNode node,
381 if (null == parentNode)
387 node =
new AvlTreeNode(
new KeyValuePair<TKey, TValue>(key, value));
395 int compareResult = key.CompareTo(parentNode.Pair.Key);
396 if (compareResult == 0)
405 if (compareResult < 0)
410 p1 = PblTreeNodeInsert(parentNode.Prev, key, value, out heightChanged, out node, out nodeAdded);
412 parentNode.PblAvlTreeSetLeft(p1);
414 if (0 == heightChanged)
422 if (parentNode._balance == 1)
424 parentNode._balance = 0;
429 if (parentNode._balance == 0)
431 parentNode._balance = -1;
438 p1 = parentNode.Prev;
440 if (p1._balance == -1)
445 parentNode.PblAvlTreeSetLeft(p1.Next);
447 p1.PblAvlTreeSetRight(parentNode);
448 parentNode._balance = 0;
451 parentNode._balance = 0;
461 p1.PblAvlTreeSetRight(p2.Prev);
463 p2.PblAvlTreeSetLeft(p1);
465 parentNode.PblAvlTreeSetLeft(p2.Next);
467 p2.PblAvlTreeSetRight(parentNode);
469 parentNode._balance = p2._balance == -1 ? 1 : 0;
471 if (p2._balance == 1)
480 parentNode._balance = 0;
488 p1 = PblTreeNodeInsert(parentNode.Next, key, value, out heightChanged, out node, out nodeAdded);
490 parentNode.PblAvlTreeSetRight(p1);
492 if (0 == heightChanged)
500 if (parentNode._balance == -1)
502 parentNode._balance = 0;
507 if (parentNode._balance == 0)
509 parentNode._balance = 1;
516 p1 = parentNode.Next;
518 if (p1._balance == 1)
523 parentNode.PblAvlTreeSetRight(p1.Prev);
525 p1.PblAvlTreeSetLeft(parentNode);
526 parentNode._balance = 0;
529 parentNode._balance = 0;
539 p1.PblAvlTreeSetLeft(p2.Next);
541 p2.PblAvlTreeSetRight(p1);
543 parentNode.PblAvlTreeSetRight(p2.Prev);
545 p2.PblAvlTreeSetLeft(parentNode);
547 if (p2._balance == 1)
549 parentNode._balance = -1;
553 parentNode._balance = 0;
556 p1._balance = p2._balance == -1 ? 1 : 0;
558 parentNode._balance = 0;
572 private AvlTreeNode PblTreeNodeBalanceLeft(
573 out
int heightChanged
594 AvlTreeNode p1 = Next;
595 int b1 = p1._balance;
602 PblAvlTreeSetRight(p1.Prev);
604 p1.PblAvlTreeSetLeft(
this);
623 AvlTreeNode p2 = p1.Prev;
624 int b2 = p2._balance;
626 p1.PblAvlTreeSetLeft(p2.Next);
628 p2.PblAvlTreeSetRight(p1);
630 PblAvlTreeSetRight(p2.Prev);
632 p2.PblAvlTreeSetLeft(
this);
643 p1._balance = b2 == -1 ? 1 : 0;
657 private AvlTreeNode PblTreeNodeBalanceRight(
658 out
int heightChanged
679 AvlTreeNode p1 = Prev;
680 int b1 = p1._balance;
687 PblAvlTreeSetLeft(p1.Next);
689 p1.PblAvlTreeSetRight(
this);
708 AvlTreeNode p2 = p1.Next;
709 int b2 = p2._balance;
711 p1.PblAvlTreeSetRight(p2.Prev);
713 p2.PblAvlTreeSetLeft(p1);
715 PblAvlTreeSetLeft(p2.Next);
717 p2.PblAvlTreeSetRight(
this);
719 _balance = b2 == -1 ? 1 : 0;
739 private AvlTreeNode PblTreeNodeRemove2(
741 out
int heightChanged,
745 AvlTreeNode r =
this;
750 p = r.Next.PblTreeNodeRemove2(q, out heightChanged, out nodeRemoved);
751 r.PblAvlTreeSetRight(p);
752 if (0 != heightChanged)
754 r = r.PblTreeNodeBalanceRight(out heightChanged);
774 internal AvlTreeNode PblTreeNodeRemove(
776 out
int heightChanged,
780 AvlTreeNode p =
this;
781 AvlTreeNode q = null;
786 int compareResult = key.CompareTo(p.Pair.Key);
788 if (compareResult < 0)
792 q = p.Prev.PblTreeNodeRemove(key, out heightChanged, out nodeRemoved);
794 p.PblAvlTreeSetLeft(q);
796 if (0 != heightChanged)
798 p = p.PblTreeNodeBalanceLeft(out heightChanged);
803 if (compareResult > 0)
807 q = p.Next.PblTreeNodeRemove(key, out heightChanged, out nodeRemoved);
809 p.PblAvlTreeSetRight(q);
811 if (0 != heightChanged)
813 p = p.PblTreeNodeBalanceRight(out heightChanged);
830 else if (null == q.Prev)
842 AvlTreeNode p1 = q.Prev.PblTreeNodeRemove2(q, out heightChanged, out nodeRemoved);
843 q.PblAvlTreeSetLeft(p1);
845 if (0 != heightChanged)
847 p = p.PblTreeNodeBalanceLeft(out heightChanged);
860 public sealed
class KeyCollection : ICollection<TKey>, ICollection
867 public sealed
class CollectionEnumerator : AvlDictionaryBaseEnumerator, IEnumerator<TKey>
881 #region IEnumerator<TKey> Member
901 #region IEnumerator Member
910 object IEnumerator.Current
921 private readonly AvlDictionary<TKey, TValue> _avlDictionary;
923 internal KeyCollection(AvlDictionary<TKey, TValue> avlDictionary)
925 _avlDictionary = avlDictionary;
928 #region ICollection<TKey> Member
937 public void Add(TKey item)
939 throw new NotSupportedException(
"The AvlDictionary.KeyCollection is read-only.");
951 throw new NotSupportedException(
"The AvlDictionary.KeyCollection is read-only.");
967 public bool Contains(TKey item)
969 return _avlDictionary.ContainsKey(item);
997 public void CopyTo(TKey[] array,
int index)
1001 throw new ArgumentNullException(
"array");
1005 throw new ArgumentOutOfRangeException(
"index",
"index is less than zero.");
1007 if (index >= array.Length)
1009 throw new ArgumentException(
"index is equal to or greater than the length of array.");
1012 if (_avlDictionary.Size == 0)
1017 if (index + _avlDictionary.Size > array.Length)
1019 throw new ArgumentException(
"number of elements in the source AvlDictionary.KeyCollection is greater than the available space from index to the end of the destination array.");
1022 IEnumerator<TKey> en = GetEnumerator();
1023 for (
int i = 0; en.MoveNext(); i++)
1025 array[i + index] = en.Current;
1039 get {
return _avlDictionary.Count; }
1049 public bool IsReadOnly
1051 get {
return true; }
1061 public bool Remove(TKey item)
1063 throw new NotSupportedException(
"The AvlDictionary.KeyCollection is read-only.");
1068 #region IEnumerable<TKey> Member
1077 public IEnumerator<TKey> GetEnumerator()
1079 return new CollectionEnumerator(_avlDictionary);
1084 #region IEnumerable Member
1093 IEnumerator IEnumerable.GetEnumerator()
1095 return new CollectionEnumerator(_avlDictionary);
1100 #region ICollection Member
1127 public void CopyTo(Array array,
int index)
1131 throw new ArgumentNullException(
"array");
1135 throw new ArgumentOutOfRangeException(
"index",
"index is less than zero.");
1137 if (index >= array.Length)
1139 throw new ArgumentException(
"index is equal to or greater than the length of array.");
1147 if (index + Count > array.Length)
1149 throw new ArgumentException(
"number of elements in the source AvlDictionary.KeyCollection is greater than the available space from index to the end of the destination array.");
1152 IEnumerator<TKey> en = GetEnumerator();
1153 for (
int i = 0; en.MoveNext(); i++)
1155 array.SetValue(en.Current, i + index);
1166 public bool IsSynchronized
1168 get {
return false; }
1178 public object SyncRoot
1180 get {
return _avlDictionary._lock; }
1191 public sealed
class ValueCollection : ICollection<TValue>, ICollection
1197 public sealed
class CollectionEnumerator : AvlDictionaryBaseEnumerator, IEnumerator<TValue>
1211 #region IEnumerator<TKey> Member
1220 public TValue Current
1224 return CurrentValue;
1230 #region IEnumerator Member
1239 object IEnumerator.Current
1243 return CurrentValue;
1250 private readonly AvlDictionary<TKey, TValue> _avlDictionary;
1252 internal ValueCollection(AvlDictionary<TKey, TValue> avlDictionary)
1254 _avlDictionary = avlDictionary;
1257 #region ICollection<TValue> Member
1266 public void Add(TValue item)
1268 throw new NotSupportedException(
"The AvlDictionary.ValueCollection is read-only.");
1280 throw new NotSupportedException(
"The AvlDictionary.ValueCollection is read-only.");
1296 public bool Contains(TValue item)
1298 if (_avlDictionary.Size == 0)
1305 for (IEnumerator<TValue> en = GetEnumerator(); en.MoveNext(); )
1307 if (null == en.Current)
1315 for (IEnumerator<TValue> en = GetEnumerator(); en.MoveNext(); )
1317 if (item.Equals(en.Current))
1351 public void CopyTo(TValue[] array,
int index)
1355 throw new ArgumentNullException(
"array");
1359 throw new ArgumentOutOfRangeException(
"index",
"index is less than zero.");
1361 if (index >= array.Length)
1363 throw new ArgumentException(
"index is equal to or greater than the length of array.");
1366 if (_avlDictionary.Size == 0)
1371 if (index + _avlDictionary.Size > array.Length)
1373 throw new ArgumentException(
"number of elements in the source AvlDictionary.ValueCollection is greater than the available space from index to the end of the destination array.");
1376 IEnumerator<TValue> en = GetEnumerator();
1377 for (
int i = 0; en.MoveNext(); i++)
1379 array[i + index] = en.Current;
1393 get {
return _avlDictionary.Count; }
1403 public bool IsReadOnly
1405 get {
return true; }
1415 public bool Remove(TValue item)
1417 throw new NotSupportedException(
"The AvlDictionary.ValueCollection is read-only.");
1422 #region IEnumerable<TValue> Member
1431 public IEnumerator<TValue> GetEnumerator()
1433 return new CollectionEnumerator(_avlDictionary);
1438 #region IEnumerable Member
1447 IEnumerator IEnumerable.GetEnumerator()
1449 return new CollectionEnumerator(_avlDictionary);
1454 #region ICollection Member
1481 public void CopyTo(Array array,
int index)
1485 throw new ArgumentNullException(
"array");
1489 throw new ArgumentOutOfRangeException(
"index",
"index is less than zero.");
1491 if (index >= array.Length)
1493 throw new ArgumentException(
"index is equal to or greater than the length of array.");
1501 if (index + Count > array.Length)
1503 throw new ArgumentException(
"number of elements in the source AvlDictionary.ValueCollection is greater than the available space from index to the end of the destination array.");
1506 IEnumerator<TValue> en = GetEnumerator();
1507 for (
int i = 0; en.MoveNext(); i++)
1509 array.SetValue(en.Current, i + index);
1520 public bool IsSynchronized
1522 get {
return false; }
1532 public object SyncRoot
1534 get {
return _avlDictionary._lock; }
1540 private AvlTreeNode _rootNode;
1542 private long _changeCounter;
1544 private readonly
object _lock;
1546 private int Size {
get;
set; }
1548 private readonly KeyCollection _keys;
1550 private readonly ValueCollection _values;
1552 private AvlTreeNode FindNode(TKey key)
1559 AvlTreeNode node = _rootNode;
1561 while (node != null)
1563 int compareResult = key.CompareTo(node.Pair.Key);
1564 if (compareResult == 0)
1569 node = compareResult < 0 ? node.Prev : node.Next;
1574 private AvlTreeNode AddNode(TKey key, TValue value, out
bool nodeAdded)
1578 throw new ArgumentNullException(
"key");
1583 throw new NotSupportedException(
"The AvlDictionary is read-only.");
1589 AvlTreeNode insertResult = AvlTreeNode.PblTreeNodeInsert(_rootNode, key, value, out heightChanged, out node, out nodeAdded);
1601 insertResult.Parent = null;
1602 _rootNode = insertResult;
1609 public AvlDictionary()
1612 _lock =
new object();
1613 _keys =
new KeyCollection(
this);
1614 _values =
new ValueCollection(
this);
1634 public AvlDictionary(IEnumerable<KeyValuePair<TKey, TValue>> dictionary)
1637 if (null == dictionary)
1639 throw new ArgumentNullException(
"dictionary");
1642 for (IEnumerator<KeyValuePair<TKey, TValue>> en = dictionary.GetEnumerator(); en.MoveNext(); )
1648 #region IDictionary<TKey,TValue> Member
1668 public void Add(TKey key, TValue value)
1671 AddNode(key, value, out nodeAdded);
1674 throw new ArgumentException(
string.Format(
"An element with the same key '{0}' already exists in the AvlDictionary.", key));
1693 public bool ContainsKey(TKey key)
1695 return FindNode(key) != null;
1705 public ICollection<TKey> Keys
1707 get {
return _keys; }
1729 public bool Remove(TKey key)
1733 throw new ArgumentNullException(
"key");
1738 throw new NotSupportedException(
"The AvlDictionary is read-only.");
1741 if (null == _rootNode)
1749 AvlTreeNode removeResult = _rootNode.PblTreeNodeRemove(key, out heightChanged, out nodeRemoved);
1758 if (removeResult != null)
1760 removeResult.Parent = null;
1762 _rootNode = removeResult;
1789 public bool TryGetValue(TKey key, out TValue value)
1793 throw new ArgumentNullException(
"key");
1796 AvlTreeNode node = FindNode(key);
1799 value =
default(TValue);
1803 value = node.Pair.Value;
1813 public ICollection<TValue> Values
1815 get {
return _values; }
1841 public TValue
this[TKey key]
1846 if (TryGetValue(key, out value))
1850 throw new KeyNotFoundException(
"key does not exist in the collection.");
1856 throw new NotSupportedException(
"The AvlDictionary is read-only.");
1860 AvlTreeNode node = AddNode(key, value, out nodeAdded);
1865 if (null != node.Pair.Value)
1867 node.Pair =
new KeyValuePair<TKey, TValue>(key, value);
1872 if (!value.Equals(node.Pair.Value))
1874 node.Pair =
new KeyValuePair<TKey, TValue>(key, value);
1883 #region ICollection<KeyValuePair<TKey,TValue>> Member
1900 public void Add(KeyValuePair<TKey, TValue> item)
1903 AvlTreeNode node = AddNode(item.Key, item.Value, out nodeAdded);
1906 throw new ArgumentException(
string.Format(
"An element with the same key '{0}' already exists in the AvlDictionary.", item.Key));
1921 throw new NotSupportedException(
"The AvlDictionary is read-only.");
1940 public bool Contains(KeyValuePair<TKey, TValue> item)
1942 AvlTreeNode node = FindNode(item.Key);
1947 return item.Equals(node.Pair);
1974 public void CopyTo(KeyValuePair<TKey, TValue>[] array,
int index)
1978 throw new ArgumentNullException(
"array");
1982 throw new ArgumentOutOfRangeException(
"index",
"index is less than zero.");
1984 if (index >= array.Length)
1986 throw new ArgumentException(
"index is equal to or greater than the length of array.");
1994 if (index + Size > array.Length)
1996 throw new ArgumentException(
"number of elements in the source AvlDictionary is greater than the available space from index to the end of the destination array.");
1999 IEnumerator<KeyValuePair<TKey, TValue>> en = GetEnumerator();
2000 for (
int i = 0; en.MoveNext(); i++)
2002 array[i + index] = en.Current;
2015 get {
return Size; }
2024 public bool IsReadOnly
2026 get {
return false; }
2046 public bool Remove(KeyValuePair<TKey, TValue> item)
2050 throw new NotSupportedException(
"The AvlDictionary is read-only.");
2053 AvlTreeNode node = FindNode(item.Key);
2058 if (item.Equals(node.Pair))
2068 #region IEnumerable<KeyValuePair<TKey,TValue>> Member
2076 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
2078 return new Enumerator(
this);
2083 #region IEnumerable Member
2091 IEnumerator IEnumerable.GetEnumerator()
2093 return new Enumerator(
this);
2098 #region ICollection Member
2123 public void CopyTo(Array array,
int index)
2127 throw new ArgumentNullException(
"array");
2131 throw new ArgumentOutOfRangeException(
"index",
"index is less than zero.");
2133 if (index >= array.Length)
2135 throw new ArgumentException(
"index is equal to or greater than the length of array.");
2143 if (index + Size > array.Length)
2145 throw new ArgumentException(
"number of elements in the source AvlDictionary is greater than the available space from index to the end of the destination array.");
2148 IEnumerator<KeyValuePair<TKey, TValue>> en = GetEnumerator();
2149 for (
int i = 0; en.MoveNext(); i++)
2151 array.SetValue(en.Current, i + index);
2161 public bool IsSynchronized
2163 get {
return false; }
2172 public object SyncRoot
2174 get {
return _lock; }