【问题标题】:An efficient way to implement a custom generic list/queue/stack combination实现自定义通用列表/队列/堆栈组合的有效方法
【发布时间】:2012-09-12 11:58:02
【问题描述】:

我发现不止一种情况,泛型集合需要在某个时间点被视为列表,而在另一个时间点被视为堆栈或队列。对于我目前正在开发的应用程序,使用三个单独的对象是没有意义的。

我能想到的最简单的解决方案是在标准 List 上实现 Queue/Dequeue/Push/Pop/Peek 函数。此外(不包括在下面的代码中),对 T 应用了一个接口约束,允许该类为每个列表、队列和堆栈维护一个位置/序数索引。

public class List<T>:
    System.Collections.Generic.List<T>
{
    private object SyncRoot = new object();

    public void Enqueue (T item)
    {
        lock (this.SyncRoot)
        {
            this.Add(item);
        }
    }

    public T Dequeue ()
    {
        T item = default(T);

        lock (this.SyncRoot)
        {
            if (this.Count > 0)
            {
                item = this [0];
                this.RemoveAt(0);
            }
        }

        return (item);
    }

    public void Push (T item)
    {
        lock (this.SyncRoot)
        {
            this.Add(item);
        }
    }

    public T Pop ()
    {
        T item = default(T);

        lock (this.SyncRoot)
        {
            if (this.Count > 0)
            {
                item = this [this.Count - 1];
                this.RemoveAt(this.Count - 1);
            }
        }

        return (item);
    }

    public T PeekQueue ()
    {
        T item = default(T);

        lock (this.SyncRoot)
        {
            if (this.Count > 0)
            {
                item = this [0];
            }
        }

        return (item);
    }

    public T PeekStack ()
    {
        T item = default(T);

        lock (this.SyncRoot)
        {
            if (this.Count > 0)
            {
                item = this [this.Count - 1];
            }
        }

        return (item);
    }
}
  • 由于这是一个粗略的即时实现,我不确定要注意哪些极端情况,因此希望提供指向任何现有此类实现的指针或链接。
  • 其次,我对大型列表的性能持怀疑态度。从 List 继承的决定是否比对大型列表使用说 LinkedList 更好。就我而言,添加/删除项目比枚举列表具有更高的优先级。

【问题讨论】:

  • 注意:我确实意识到这样一个类不会成为其他开发人员使用的好选择,因为结合列表、队列和堆栈的功能可能会非常违反直觉,具体取决于您如何使用它们.
  • @hagensoft:我似乎无法访问页面内容。它仅部分加载。请把要点贴在这里好吗?
  • 您具体要求列表的哪个方面?是按索引访问吗?对于队列/堆栈的组合,听起来您要求的是一个双端队列(您可以在其中添加、删除和查看任一端的项目),对吗?
  • @Damien_The_Unbeliever:实际上都是。双端队列加上索引任意访问。

标签: c# .net list stack queue


【解决方案1】:

这里是如何使用扩展方法完成类似的行为... http://weblogs.asp.net/bsimser/archive/2011/01/13/generic-pop-and-push-for-list-lt-t-gt.aspx

通用弹出和推送列表

这是我用来扩展通用 List 类的一个小 sn-p 类似于 Stack 类的功能。

Stack 类很棒,但它生活在自己的世界中 系统对象。有一个可以做的列表不是很好吗 相同的?代码如下:

public static class ExtensionMethods    
{ 
    public static T Pop<T>(this List<T> theList)    
    {              
        var local = theList[theList.Count - 1];    
        theList.RemoveAt(theList.Count - 1);    
        return local;   
     }

     public static void Push<T>(this List<T> theList, T item)   
     {   
        theList.Add(item);   
     }   
}

这是一个简单的扩展,但我发现它很有用,希望你会 也!享受吧。

也是扩展方法的链接 http://msdn.microsoft.com/en-us/library/bb383977.aspx

【讨论】:

    【解决方案2】:

    我猜你必须使用数组作为内部数据存储,它是如何在.NET List 和其他泛型中实现的。例如,由于对内部数组中所有元素的无用处理,而不是开始索引移动,代码的出队效率低下。在ILSpy中可以看到C#反编译:

    // System.Collections.Generic.List<T>
    /// <summary>Removes the element at the specified index of the <see cref="T:System.Collections.Generic.List`1" />.</summary>
    /// <param name="index">The zero-based index of the element to remove.</param>
    /// <exception cref="T:System.ArgumentOutOfRangeException">
    ///   <paramref name="index" /> is less than 0.-or-<paramref name="index" /> is equal to or greater than <see cref="P:System.Collections.Generic.List`1.Count" />.</exception>
    public void RemoveAt(int index)
    {
        if (index >= this._size)
        {
            ThrowHelper.ThrowArgumentOutOfRangeException();
        }
        this._size--;
        if (index < this._size)
        {
            Array.Copy(this._items, index + 1, this._items, index, this._size - index);
        }
        this._items[this._size] = default(T);
        this._version++;
    }
    

    其他功能也可以稍微改进一下。

    此外,我注意到 .NET Stack 泛型实现比 List 泛型实现运行缓慢。我认为这是因为在提取时将默认值分配给堆栈的最后一个元素,这与 List 不同:

    // System.Collections.Generic.Stack<T>
    /// <summary>Removes and returns the object at the top of the <see cref="T:System.Collections.Generic.Stack`1" />.</summary>
    /// <returns>The object removed from the top of the <see cref="T:System.Collections.Generic.Stack`1" />.</returns>
    /// <exception cref="T:System.InvalidOperationException">The <see cref="T:System.Collections.Generic.Stack`1" /> is empty.</exception>
    public T Pop()
    {
        if (this._size == 0)
        {
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);
        }
        this._version++;
        T result = this._array[--this._size];
        this._array[this._size] = default(T);
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-08
      • 2015-05-15
      • 1970-01-01
      • 2014-12-23
      • 2010-10-15
      • 1970-01-01
      • 2018-06-14
      相关资源
      最近更新 更多