BinaryTree.cs
上传用户:sex100000
上传日期:2013-11-09
资源大小:1377k
文件大小:9k
源码类别:

GIS编程

开发平台:

C#

  1. // Copyright 2005, 2006 - Morten Nielsen (www.iter.dk)
  2. //
  3. // This file is part of SharpMap.
  4. // SharpMap is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. // 
  9. // SharpMap is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU Lesser General Public License for more details.
  13. // You should have received a copy of the GNU Lesser General Public License
  14. // along with SharpMap; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  16. using System;
  17. using System.Diagnostics;
  18. using System.Collections.Generic;
  19. namespace SharpMap.Utilities.Indexing
  20. {
  21. // Binary Tree not working yet on Mono 
  22. // see bug: http://bugzilla.ximian.com/show_bug.cgi?id=78502
  23. #if !MONO
  24. [Serializable]
  25. internal class Node<T,U> where T : IComparable<T>
  26. {
  27. public Node<T, U> LeftNode;
  28. public Node<T, U> RightNode;
  29. public BinaryTree<T,U>.ItemValue Item;
  30. public Node() : this(default(T),default(U),null,null)
  31. {
  32. }
  33. public Node(T item, U itemIndex) : this(item,itemIndex,null,null)
  34. {
  35. }
  36. public Node(BinaryTree<T, U>.ItemValue value):this(value.Value,value.Id,null,null)
  37. {
  38. }
  39. public Node(T item, U itemIndex, Node<T, U> right, Node<T, U> left)
  40. {
  41. RightNode = right;
  42. LeftNode = left;
  43. Item = new BinaryTree<T, U>.ItemValue();
  44. Item.Value = item;
  45. Item.Id = itemIndex;
  46. }
  47. public static bool operator >(Node<T, U> lhs, Node<T, U> rhs)
  48. {
  49. int res = lhs.Item.Value.CompareTo(rhs.Item.Value);
  50. return res > 0;
  51. }
  52. public static bool operator <(Node<T, U> lhs, Node<T, U> rhs)
  53. {
  54. int res = lhs.Item.Value.CompareTo(rhs.Item.Value);
  55. return res < 0;
  56. }
  57. }
  58. /// <summary>
  59. /// The BinaryTree class are used for indexing values to enhance the speed of queries
  60. /// </summary>
  61. /// <typeparam name="T">Value type to be indexed</typeparam>
  62. /// <typeparam name="U">Value ID type</typeparam>
  63. [Serializable]
  64. public class BinaryTree<T, U> where T : IComparable<T>
  65. {
  66. private Node<T, U> root;
  67. /// <summary>
  68. /// A value in a <see cref="BinaryTree&lt;T, U&gt;"/>.
  69. /// </summary>
  70. public struct ItemValue
  71. {
  72. /// <summary>
  73. /// Value
  74. /// </summary>
  75. public T Value;
  76. /// <summary>
  77. /// Identifier for the value
  78. /// </summary>
  79. public U Id;
  80. /// <summary>
  81. /// Creates an instance of an item in a <see cref="BinaryTree&lt;T, U&gt;"/>.
  82. /// </summary>
  83. /// <param name="value">Value</param>
  84. /// <param name="id">Identifier for the value</param>
  85. public ItemValue(T value, U id)
  86. {
  87. Value = value; Id = id;
  88. }
  89. }
  90. /// <summary>
  91. /// Initializes a new instance of the generic binary tree.
  92. /// </summary>
  93. public BinaryTree()
  94. {
  95. root = new Node<T, U>();
  96. }
  97. #region Read/Write index to/from a file
  98. /*
  99. private const double INDEXFILEVERSION = 1.0;
  100. public void SaveToFile(string filename)
  101. {
  102. System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create);
  103. System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fs);
  104. bw.Write(INDEXFILEVERSION); //Save index version
  105. bw.Write(typeof(T).ToString());
  106. bw.Write(typeof(U).ToString());
  107. //SaveNode(this, ref bw);
  108. //bw.Write(root);
  109. bw.Close();
  110. fs.Close();
  111. }
  112. */
  113. #endregion
  114. /// <summary>
  115. /// Inserts a value into the tree
  116. /// </summary>
  117. /// <param name="items"></param>
  118. public void Add(params ItemValue[] items)
  119. {
  120. Array.ForEach(items, Add);
  121. }
  122. /// <summary>
  123. /// Inserts a value into the tree
  124. /// </summary>
  125. /// <param name="item"></param>
  126. public void Add(ItemValue item)
  127. {
  128. Add(new Node<T, U>(item.Value, item.Id), root);
  129. }
  130. /// <summary>
  131. /// Inserts a node into the tree
  132. /// </summary>
  133. /// <param name="newNode"></param>
  134. /// <param name="root"></param>
  135. private void Add(Node<T, U> newNode, Node<T, U> root)
  136. {
  137. if (newNode > root)
  138. {
  139. if (root.RightNode == null)
  140. {
  141. root.RightNode = newNode;
  142. return;
  143. }
  144. Add(newNode, root.RightNode);
  145. }
  146. if (newNode < root)
  147. {
  148. if (root.LeftNode == null)
  149. {
  150. root.LeftNode = newNode;
  151. return;
  152. }
  153. Add(newNode, root.LeftNode);
  154. }
  155. }
  156. #region IEnumerables
  157. /// <summary>
  158. /// Gets an enumerator for all the values in the tree in ascending order
  159. /// </summary>
  160. public IEnumerable<ItemValue> InOrder
  161. {
  162. get { return ScanInOrder(root.RightNode); }
  163. }
  164. /// <summary>
  165. /// Gets and enumerator for the values between min and max in ascending order
  166. /// </summary>
  167. /// <param name="min"></param>
  168. /// <param name="max"></param>
  169. /// <returns>Enumerator</returns>
  170. public IEnumerable<ItemValue> Between(T min,T max)
  171. {
  172. return ScanBetween(min, max, root.RightNode);
  173. }
  174. /// <summary>
  175. /// Enumerates the objects whose string-representation starts with 'str'
  176. /// </summary>
  177. /// <param name="str"></param>
  178. /// <returns>Enumerator</returns>
  179. public IEnumerable<ItemValue> StartsWith(string str)
  180. {
  181. return ScanString(str.ToUpper(), root.RightNode);
  182. }
  183. /// <summary>
  184. /// Enumerates all objects with the specified value
  185. /// </summary>
  186. /// <param name="value">Value to search for</param>
  187. /// <returns>Enumerator</returns>
  188. public IEnumerable<ItemValue> Find(T value)
  189. {
  190. return ScanFind(value, root.RightNode);
  191. }
  192. private IEnumerable<ItemValue> ScanFind(T value, Node<T, U> root)
  193. {
  194. if (root.Item.Value.CompareTo(value) > 0)
  195. {
  196. if (root.LeftNode != null)
  197. {
  198. if (root.LeftNode.Item.Value.CompareTo(value) > 0)
  199. foreach (ItemValue item in ScanFind(value, root.LeftNode))
  200. {
  201. yield return item;
  202. }
  203. }
  204. }
  205. if (root.Item.Value.CompareTo(value) == 0)
  206. yield return root.Item;
  207. if (root.Item.Value.CompareTo(value) < 0)
  208. {
  209. if (root.RightNode != null)
  210. {
  211. if (root.RightNode.Item.Value.CompareTo(value) > 0)
  212. foreach (ItemValue item in ScanFind(value, root.RightNode))
  213. {
  214. yield return item;
  215. }
  216. }
  217. }
  218. }
  219. private IEnumerable<ItemValue> ScanString(string val, Node<T, U> root)
  220. {
  221. if (root.Item.Value.ToString().Substring(0,val.Length).ToUpper().CompareTo(val) > 0)
  222. {
  223. if (root.LeftNode != null)
  224. {
  225. if (root.LeftNode.Item.Value.ToString().ToUpper().StartsWith(val))
  226. foreach (ItemValue item in ScanString(val, root.LeftNode))
  227. {
  228. yield return item;
  229. }
  230. }
  231. }
  232. if (root.Item.Value.ToString().ToUpper().StartsWith(val))
  233. yield return root.Item;
  234. if (root.Item.Value.ToString().CompareTo(val) < 0)
  235. {
  236. if (root.RightNode != null)
  237. {
  238. if (root.RightNode.Item.Value.ToString().Substring(0, val.Length).ToUpper().CompareTo(val) > 0)
  239. foreach (ItemValue item in ScanString(val, root.RightNode))
  240. {
  241. yield return item;
  242. }
  243. }
  244. }
  245. }
  246. private IEnumerable<ItemValue> ScanBetween(T min, T max, Node<T, U> root)
  247. {
  248. if (root.Item.Value.CompareTo(min) > 0)
  249. {
  250. if (root.LeftNode != null)
  251. {
  252. if (root.LeftNode.Item.Value.CompareTo(min) > 0)
  253. foreach (ItemValue item in ScanBetween(min, max, root.LeftNode))
  254. {
  255. yield return item;
  256. }
  257. }
  258. }
  259. if (root.Item.Value.CompareTo(min) > 0 && root.Item.Value.CompareTo(max) < 0)
  260. yield return root.Item;
  261. if (root.Item.Value.CompareTo(max) < 0)
  262. {
  263. if (root.RightNode != null)
  264. {
  265. if (root.RightNode.Item.Value.CompareTo(min) > 0)
  266. foreach (ItemValue item in ScanBetween(min, max, root.RightNode))
  267. {
  268. yield return item;
  269. }
  270. }
  271. }
  272. }
  273. private IEnumerable<ItemValue> ScanInOrder(Node<T, U> root)
  274. {
  275. if (root.LeftNode != null)
  276. {
  277. foreach (ItemValue item in ScanInOrder(root.LeftNode))
  278. {
  279. yield return item;
  280. }
  281. }
  282. yield return root.Item;
  283. if (root.RightNode != null)
  284. {
  285. foreach (ItemValue item in ScanInOrder(root.RightNode))
  286. {
  287. yield return item;
  288. }
  289. }
  290. }
  291. #endregion
  292. /// <summary>
  293. /// This is the classic computer science binary tree iteration 
  294. /// </summary>
  295. public void TraceTree()
  296. {
  297. TraceInOrder(root.RightNode);
  298. }
  299. private void TraceInOrder(Node<T, U> root)
  300. {
  301. if (root.LeftNode != null)
  302. TraceInOrder(root.LeftNode);
  303. Trace.WriteLine(root.Item.ToString());
  304. if (root.RightNode != null)
  305. TraceInOrder(root.RightNode);
  306. }
  307. }
  308. #endif
  309. }