2016-07-07 104 views
0

下面是一個示例 - 我想基於C#中的現有LinkedList實現DropoutStack(具有固定最大大小的堆棧,並且在超大時從底部移除元素)。 (這是想法的來源:Limit the size of a generic collection?) 但是,至少有兩種實現方式。如何根據現有策略選擇實施新數據結構的策略?

1)來自現有數據結構(LinkedList)的新數據結構(DropOutStack)是繼承的。就像the answer

public class LimitedSizeStack<T> : LinkedList<T> 
{ 
private readonly int _maxSize; 
public LimitedSizeStack(int maxSize) 
{ 
    _maxSize = maxSize; 
} 

public void Push(T item) 
{ 
    this.AddFirst(item); 

    if(this.Count > _maxSize) 
    this.RemoveLast(); 
} 

public T Pop() 
{ 
    var item = this.First.Value; 
    this.RemoveFirst(); 
    return item; 
} 
} 

2)新的數據結構擁有現有之一。例如:

public class LimitedSizeStack<T> 
    { 
    private readonly int _maxSize; 
    private LinkedList<T> _list; 
    public LimitedSizeStack(int maxSize) 
    { 
     _maxSize = maxSize; 
     _list = new LinkedList<T>(); 
    } 

    public void Push(T item) 
    { 
     _list.AddFirst(item); 

     if(_list.Count > _maxSize) 
     _list.RemoveLast(); 
    } 

    public T Pop() 
    { 
     var item = _list.First.Value; 
     _list.RemoveFirst(); 
     return item; 
    } 

有兩個方法的優點&缺點。
對於1:我們不需要關心實施常用方法,如清除()計數;但其他與DropOutStack無關的方法也將被公開(例如,Find(),AddBefore())。
對於2:這是相反的。不相關的方法是隱藏的,但我們需要重新實現常用的方法。

我的問題是:
1)是否有任何實施慣例,即選擇一個選項總是更好?
2)作出決定時是否還有其他因素需要考慮(例如效率和記憶)?

+0

我認爲最終會真正到來在執行和方法暴露方面的困難方面。 – Jashaszun

+1

我認爲這裏的基本設計問題是「是一個有限尺寸堆棧」還是僅僅在某些方面類似於堆棧?「IsA =>繼承構成。 –

回答

1

你幾乎從不想使用繼承。只有當你有一個明確意味着被覆蓋的抽象基本集合時(哪個LinkedList不是)。您將公開堆棧的實現細節,並讓用戶在預期的公共API之外任意操作它。一個堆棧不應該有像「AddBefore」,「AddAfter」,「AddFirst」,「AddLast」的東西。

此外,鏈表是不是一個尺寸有限的堆棧一個不錯的選擇,一個數組爲固定大小的數據結構更爲合適:

public class LimitedSizeStack<T> 
{ 
    private T[] items; 
    private int top; 
    private int count; 
    public LimitedSizeStack(int size) 
    { 
     items = new T[size]; 
     top = size - 1; 
     count = 0; 
    } 
    public bool IsEmpty { get { return count == 0; } } 
    public T Peek() 
    { 
     if (IsEmpty) 
      throw new Exception("Stack is empty"); 
     return items[top]; 
    } 
    public T Pop() 
    { 
     if (IsEmpty) 
      throw new Exception("Stack is empty"); 
     count--; 
     var result = items[top]; 
     top--; 
     if (top < 0) 
      top += items.Length; 
     return result; 
    } 
    public void Push(T value) 
    { 
     top++; 
     if (top >= items.Length) 
      top -= items.Length; 
     items[top] = value; 
     if (count < items.Length) 
      count++; 
    } 
}