C# 性能:在堆栈上调用reverse或将项目弹出到数组中哪个更快

C# 性能:在堆栈上调用reverse或将项目弹出到数组中哪个更快,c#,performance,C#,Performance,我想知道哪种实现的性能更好: 我需要清除堆栈中的所有项目,头10个项目除外 然后,必须按照原始顺序将这10个元素放入堆栈中 我想到了两种方法 第一: FilterRecord[] records = new FilterRecord[10]; for (int i = 0; i < records.Length; i++) { records[i] = _InternalCollection.Pop(); }

我想知道哪种实现的性能更好:

我需要清除堆栈中的所有项目,头10个项目除外

然后,必须按照原始顺序将这10个元素放入堆栈中

我想到了两种方法

第一:

FilterRecord[] records = new FilterRecord[10];

       for (int i = 0; i < records.Length; i++)
       {
           records[i] = _InternalCollection.Pop();
       }

       _InternalCollection.Clear();

       for (int i = records.Length - 1; i >= 0; i--)
       {
           _InternalCollection.Push(records[i]);
       }
FilterRecord[]记录=新的FilterRecord[10];
for(int i=0;i=0;i--)
{
_内部收集.推送(记录[i]);
}
第二点:

int count = _InternalCollection.Count - 10;
               _InternalCollection.Reverse();


               for (int i = 0; i < count; i++)
               {
                   _InternalCollection.Pop();
               }

               _InternalCollection.Reverse();
int count=\u InternalCollection.count-10;
_InternalCollection.Reverse();
for(int i=0;i

欢迎提供任何帮助、指导方针或其他建议。

这取决于情况,您假设Reverse()方法并没有做到这一点。只有两种方法可以知道:1)运行代码并告诉我们2。)查找Reverse()的实现。

这取决于,您假设Reverse()方法并没有做到这一点。只有两种方法可以知道:1)运行代码并告诉我们2)查找Reverse()的实现。

您的第一个算法有两个for循环,所以O(2N)。第二个算法有一个for循环,但我们必须假设内部Reverse()是一个O(N)操作,所以它是O(3N)


我不确定第一个算法中的Clear()调用是O(N)还是O(C)。

第一个算法有两个for循环,所以O(2N)。第二个算法有一个for循环,但我们必须假设内部Reverse()是一个O(N)操作,所以它是O(3N)


我不确定第一个算法中的Clear()调用是O(N)还是O(C)。

这类事情通常很难判断。只需要做一个非常大的堆栈,调用这两个堆栈并计时。那你就知道了。

这类事情通常很难分辨。只需要做一个非常大的堆栈,调用这两个堆栈并计时。那你就知道了。

这要看情况而定。你可以做两件事:

  • 通过运行几个小时来测试它 百次迭代(更少或更多 (取决于尺寸)
  • 看看它们的实现
分析实现堆栈的方法(概念上),使用reverse将是最慢的,因为它必须弹出堆栈中的所有内容,然后以相反的顺序将它们放回。如果在内部,它只是选择了一个不同的开始弹出索引,它可能会更快


简单地说,无论采用哪种方式,使用Reverse()似乎效率低下,因为您要执行两次该操作。

这取决于具体情况。你可以做两件事:

  • 通过运行几个小时来测试它 百次迭代(更少或更多 (取决于尺寸)
  • 看看它们的实现
分析实现堆栈的方法(概念上),使用reverse将是最慢的,因为它必须弹出堆栈中的所有内容,然后以相反的顺序将它们放回。如果在内部,它只是选择了一个不同的开始弹出索引,它可能会更快


无论哪种方式,简单地说,使用Reverse()似乎效率低下,因为您要执行两次该操作。

我建议您查看一下Reverse()的实际实现-您可能会发现其中的有用之处。

我建议您查看一下Reverse()的实际实现-您可能会发现这一点很有用。

如果堆栈中的项目很少,那么差异很小,不值得优化

如果堆栈中有许多项,这将是最快的:

FilterRecord[] records = new FilterRecord[10];

for (int i = 0; i < records.Length; i++) {
   records[i] = _InternalCollection.Pop();
}

_InternalCollection = new Stack<FilterRecord>();

for (int i = records.Length - 1; i >= 0; i--) {
   _InternalCollection.Push(records[i]);
}
FilterRecord[]记录=新的FilterRecord[10];
for(int i=0;i=0;i--){
_内部收集.推送(记录[i]);
}
也就是说,在你得到想要保留的物品后,把当前的堆栈扔掉,让垃圾收集器来处理。如果使用Clear方法,则会从堆栈中删除引用,但会保留其容量

由于不管堆栈中有多少项,您只需触摸其中的十项,因此这是一个O(1)操作,而不是O(n)操作


(请注意,声明数组时使用的是数组的大小,而不是最高索引。)

如果堆栈中的项目很少,那么差异很小,不值得优化

如果堆栈中有许多项,这将是最快的:

FilterRecord[] records = new FilterRecord[10];

for (int i = 0; i < records.Length; i++) {
   records[i] = _InternalCollection.Pop();
}

_InternalCollection = new Stack<FilterRecord>();

for (int i = records.Length - 1; i >= 0; i--) {
   _InternalCollection.Push(records[i]);
}
FilterRecord[]记录=新的FilterRecord[10];
for(int i=0;i=0;i--){
_内部收集.推送(记录[i]);
}
也就是说,在你得到想要保留的物品后,把当前的堆栈扔掉,让垃圾收集器来处理。如果使用Clear方法,则会从堆栈中删除引用,但会保留其容量

由于不管堆栈中有多少项,您只需触摸其中的十项,因此这是一个O(1)操作,而不是O(n)操作


(请注意,声明数组时使用的是数组的大小,而不是最高索引。)

我认为避免从堆栈中弹出项将比您建议的两种方法更能提高代码的性能。我建议使用linq分配一个包含堆栈上最后一项内容的新堆栈,如下所示:

var newStack = new Stack<FilterRecord>( 
   _InternalCollection.Take( 10 )
                      .Reverse() );

_InternalCollection = newStack;

我认为避免从堆栈中弹出项将提高代码的性能
    public class CustomStack<T>
    {
        private LinkedList<T> list;

        public CustomStack()
        {
            list = new LinkedList<T>();
        }

        public void Push(T item)
        {
            list.AddFirst(item);
        }

        public T Pop()
        {

            var result = list.First.Value;
            list.RemoveFirst();
            return result;
        }

        public void TrimLast(int amountToLeave)
        {
            while (list.Count > amountToLeave)
            {
                list.RemoveLast();
            }
        }
    }