基於二叉查找樹的集合


     我們都知道Dictionary<TKey, TValue>查找元素非常快,其實現原理是:將你TKey的值散列到數組的指定位置,將TValue的值存入對應的位置,
 由於取和存用的是同一個算法,所以就很容易定位到TValue的位置,花費的時間基本上就是實現散列算法的時間,跟其中元素的個數沒有關系,
 故取值的時間復雜度為O(1)。
     集合無非都是基於最基礎語法的數組[],先欲分配,然后向其中添加元素,容量不夠就創建一個2倍容量的數組,將之前的元素賦值過來,將之前的數組回收,
 但基於散列算法的集合這點上有點不同,他並不是每次創建一個2倍容量的數組,為了讓元素均勻的分布到數組上,數組的容量是這么增長的:3,7,11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919,1103...
 以質數的方式增長。由於每次擴充數組的容量較小,如果要向其中添加很多元素的話,程序員又沒有預先分配內存,那就會出現多次數組的創建、復制和回收。
     一直想做個有用的東西出來,讓想用的人用,又能讓自己練練手,於是這次做了一個基於二叉查找樹的集合,我們知道在二叉查找樹中查詢元素的最優時間復雜度是O(logN)即在滿二叉樹的情況下,最壞時間復雜度是O(n)即除葉子節點外每個節點只有一個子節點,
 查找元素它也是很快的哦,而且查找的時候都只是做Int型的比較,而Dictionary<TKey, TValue>是基於一個散列算法,當然基於二插查找樹的集合也有自身的缺點:
     1:元素必須實現接口IBinaryTree,其屬性CompareValue主要用於比較生成二叉查找樹
     2:元素必須是可以new的,即不支持基礎類型int,char,string等
     3:每個節點都有左右兩個子節點,他們只是起到指針的作用,指向該節點的子節點,只需占用額外的少量內存
     4:基本上都是基於遞歸實現,元素過多的話,會棧溢出,至於原因請看我的這篇博客
    優點是常用的一些功能都有,功能如下,練手嗎,但會一直優化下去

    public class BinaryTree<T> : IDisposable, IEnumerable<T>, IEnumerable where T :IBinaryTree, new()
{
public BinaryTree();
public BinaryTree(IEnumerable<T> list);//將一個數組構造成二插查找樹
public BinaryTree(T root); //指定跟節點
public int Count { get; }//元素個數
public T this[IBinaryTree iBinaryTree] { get; }//數組索引直接訪問元素
public void Add(T t);//添加元素
public void Clear();//清除所有元素
public bool Contains(T iBinaryTree);//是否包含自定元素
public void Dispose();//釋放資源,支持using
public T Find(IBinaryTree iBinaryTree);//查找元素
public T Find(IBinaryTree iBinaryTree, TreeNode<T> node);//在指定的節點下查找元素
public T FindMax();//最大元素
public T FindMin();//最小元素
public T FindMin(TreeNode<T> node);//在指定的節點下查找最小元素
public IEnumerator<T> GetEnumerator();//返回所有元素,支持foreach
public TreeNode<T> Remove(T t);//刪除元素
public TreeNode<T> Remove(IBinaryTree iBinaryTree, TreeNode<T> node);//在指定的節點下刪除元素
public IEnumerable<T> Sort();//排序(升序)
public IEnumerable<T> ToList();//返回所有元素
}

 

源碼
namespace Utils
{
/// <summary>
/// 二叉樹接口
/// </summary>
public interface IBinaryTree
{
/// <summary>
/// 用於比較的值
/// </summary>
int CompareValue
{
get;
set;
}
}

public class TreeNode<T> where T : IBinaryTree, new()
{
public TreeNode<T> Left
{
get;
set;
}

public TreeNode<T> Right
{
set;
get;
}

public T Data
{
get;
set;
}

public TreeNode(T t)
{
this.Data = t;
}

public TreeNode()
: this(default(T))
{

}
}

/// <summary>
/// 二插查找樹
/// </summary>
public class BinaryTree<T> : IDisposable,IEnumerable<T> where T : IBinaryTree, new()
{
public BinaryTree()
{

}

public BinaryTree(T root)
{
if (root == null)
{
throw new NullReferenceException("Parameter is null");
}
Add(root);
}

public BinaryTree(IEnumerable<T> list)
{
if (list == null)
{
throw new NullReferenceException("Parameter is null");
}
foreach (var item in list)
{
Add(item);
}
}

//根節點
private TreeNode<T> root;

//添加節點(沒有檢查根節點是否為空,所以設為private)
private void Add(T t, TreeNode<T> root)
{
if (t == null)
{
return;
}
if (t.CompareValue < root.Data.CompareValue)
{
if (root.Left == null)
{
root.Left = new TreeNode<T>(t);
++Count;
}
else
{
Add(t, root.Left);
}
}
else if (t.CompareValue > root.Data.CompareValue)
{
if (root.Right == null)
{
root.Right = new TreeNode<T>(t);
++Count;
}
else
{
Add(t, root.Right);
}
}
else
{
root.Data = t;
}
}

//添加節點
public void Add(T t)
{
if (t == null)
{
return;
}
if (this.root == null)
{
this.root = new TreeNode<T>(t);
++Count;
}
else
{
Add(t, this.root);
}
}

//查找指定節點下的最小節點
public T FindMin(TreeNode<T> node)
{
if (node == null)
{
return default(T);
}
if (node.Left == null)
{
return node.Data;
}
else
{
return FindMin(node.Left);
}
}

//查找最小節點
public T FindMin()
{
return FindMin(this.root);
}

//查找最大節點
private T FindMax(TreeNode<T> node)
{
if (node.Right == null)
{
return node.Data;
}
else
{
return FindMax(node.Right);
}
}

//查找最大節點
public T FindMax()
{
return FindMax(this.root);
}

//刪除指定節點下的節點
public TreeNode<T> Remove(IBinaryTree iBinaryTree, TreeNode<T> node)
{
if (node == null)
{
return null;
}
if (iBinaryTree == null)
{
return node;
}
if (iBinaryTree.CompareValue < node.Data.CompareValue)
{
node.Left = Remove(iBinaryTree, node.Left);
}
else if (iBinaryTree.CompareValue > node.Data.CompareValue)
{
node.Right = Remove(iBinaryTree, node.Right);
}
else
{
if (node.Left != null && node.Right != null)
{
T tmpNode = FindMin(node.Right);//查找當前節點有子樹的最小節點
node.Data.CompareValue = tmpNode.CompareValue;//將右子樹的最小節點取代當前要刪除的節點
node.Right = Remove(tmpNode, node.Right);//這里是亮點,刪除當前節點右子樹的最小節點
}
else
{
if (node.Left == null)
{
node = node.Right;
}
else if (node.Right == null)
{
node = node.Left;
}
else
{
node = null;
}
if (this.root.Data.CompareValue == iBinaryTree.CompareValue)//處理根節點
{
this.root = node;
}
}
--Count;
}
return node;
}

//刪除節點
public TreeNode<T> Remove(T t)
{
if (this.root == null || t==null)
{
return null;
}
return Remove(t, this.root);
}

//查找節點
public T Find(IBinaryTree iBinaryTree, TreeNode<T> node)
{
if (node == null || iBinaryTree == null)
{
return default(T);
}
if (iBinaryTree.CompareValue < node.Data.CompareValue)
{
return Find(iBinaryTree, node.Left);
}
else if (iBinaryTree.CompareValue > node.Data.CompareValue)
{
return Find(iBinaryTree, node.Right);
}
return node.Data;
}

//查找節點
public T Find(IBinaryTree iBinaryTree)
{
return Find(iBinaryTree, this.root);
}

//是否包含指定元素
private bool Contains(IBinaryTree iBinaryTree, TreeNode<T> node)
{
if (node == null || iBinaryTree == null)
{
return false; ;
}
if (iBinaryTree.CompareValue < node.Data.CompareValue)
{
return Contains(iBinaryTree, node.Left);
}
else if (iBinaryTree.CompareValue > node.Data.CompareValue)
{
return Contains(iBinaryTree, node.Right);
}
return iBinaryTree.Equals(node.Data);
}

//是否包含指定元素
public bool Contains(T iBinaryTree)
{
return Contains(iBinaryTree, this.root);
}

//清除所有節點
public void Clear()
{
while (this.Count > 0)
{
Remove(this.root.Data);
}
this.root = new TreeNode<T>();
}

//釋放資源
public void Dispose()
{
while (this.Count > 0)
{
Remove(this.root.Data);
}
this.root = null;
}

//節點個數
public int Count
{
private set;
get;
}

//轉換成集合
public IEnumerable<T> ToList()
{
IList<T> list = new List<T>(Count);
LCR(this.root,list);
return list;
}

//以前序遍歷的方式將節點加入集合,用遞歸實現,如果元素很多可能會出現棧溢出
private void LCR(TreeNode<T> node, IList<T> list)
{
if (node == null)
{
return;
}
if (node.Left != null)
{
LCR(node.Left, list);
}
list.Add(node.Data);//添加元素
if (node.Right != null)
{
LCR(node.Right, list);
}
}

//排序
public IEnumerable<T> Sort()
{
return ToList();
}

//返回一個循環訪問集合的枚舉數
public IEnumerator<T> GetEnumerator()
{
return this.ToList().GetEnumerator();
}

//返回一個循環訪問集合的枚舉數
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}

public T this[IBinaryTree iBinaryTree]
{
get {
return this.Find(iBinaryTree);
}
}

}

public class Node : IBinaryTree
{
/// <summary>
/// 用於比較的值
/// </summary>
public int CompareValue
{
get;
set;
}

public string Name
{
get;
set;
}

public override string ToString()
{
return string.Format("CompareValue:{0},Name:{1}", this.CompareValue, this.Name);
}

}
}

 

作者:陳太漢

博客:http://www.cnblogs.com/hlxs/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM