Sweet Snippet 系列之 有序列表
阿新 • • 發佈:2018-11-23
工作中常常遇到需要使用有序列表的情況,這篇文章簡單討論一下相關實現(以 C# 中的 List<T> 為例)
使用 List<T>.Sort
很樸素的一種想法,為了維持 List 有序,我們可以在 Add 操作之後進行 Sort 操作(Remove 操作後不需要重新 Sort):
list.Add(value);
list.Sort();
該方案的缺點是時間消耗比較大,每次 Add 操作之後都要執行費時的 Sort 操作
藉助平臺庫中的 SortedList<Tkey, TValue> etc.
使用平臺庫內建的 SortedList<Tkey, TValue>,我們可以立即實現有序列表功能,這也應該是我們大部分情況下的選擇,稍有缺陷的是,平臺庫中的 SortedList 需要指定 TKey 和 TValue,這在儲存非對映類資料時(譬如儲存單一的 int 數值)顯得有些記憶體浪費~
(類似的還有 SortedDictionary<TKey, TValue>)
那 SortedSet<T> 怎麼樣?
比起內部使用陣列實現的 List 而言,目前預設使用紅黑樹實現的 SortedSet 會有更多的記憶體消耗,而且也不提供索引形式的訪問,不過在插入和刪除操作上,他更有時間優勢~
其實我們可以自己封裝
基於 List 有序這個前提,每次進行 Add 時,我們可以使用插入排序來新增元素,這樣我們便可以省去之後的 Sort 操作,而 List 本身提供的 BinarySearch(二分查詢)功能正好可以幫助我們實現插入排序~
// simple sorted list implementation using insert sort
// maintainer hugoyu
using System.Collections.Generic;
namespace Util
{
public class SortedList<T>
{
public SortedList(IComparer<T> comparer = null)
{
m_comparer = comparer;
}
public int Count
{
get
{
return m_elementList.Count;
}
}
public T this[int index]
{
get
{
return m_elementList[index];
}
}
public bool Contains(T item)
{
return m_elementList.BinarySearch(item, m_comparer) >= 0;
}
public void Add(T item)
{
var index = m_elementList.BinarySearch(item, m_comparer);
if (index < 0)
{
m_elementList.Insert(~index, item);
}
else
{
m_elementList.Insert(index, item);
}
}
public bool Remove(T item)
{
var index = m_elementList.BinarySearch(item, m_comparer);
if (index >= 0)
{
m_elementList.RemoveAt(index);
return true;
}
return false;
}
public void Clear()
{
m_elementList.Clear();
}
IComparer<T> m_comparer;
List<T> m_elementList = new List<T>();
}
}
完整的程式碼在這裡(gist)
軟體開發的核心就是權衡,下次如果你需要使用有序列表,會選擇怎麼實現呢?