1. 程式人生 > >Sweet Snippet 系列之 有序列表

Sweet Snippet 系列之 有序列表

工作中常常遇到需要使用有序列表的情況,這篇文章簡單討論一下相關實現(以 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)


軟體開發的核心就是權衡,下次如果你需要使用有序列表,會選擇怎麼實現呢?