C# 最佳.NET阵列/列表

C# 最佳.NET阵列/列表,c#,C#,所以,我需要一个项目数组。我想知道哪一个最快/最好使用(在c中),我将做以下事情: 在末尾添加元素 在开始时删除元素 查看第一个和最后一个元素(每帧) 偶尔清理一下 将其转换为普通数组(不是列表。我正在使用iTween,它要求一个普通数组。)我几乎每一帧都会这样做 那么,考虑到这些事情,什么才是最好的选择呢?特别是最后一个,因为我每一帧都在做。我应该只使用数组,还是有其他东西可以非常快速地转换为数组,并且在开始和结束时可以轻松地添加/删除元素?您可以看看 它支持在开始或结束时检查、添加和删除项目

所以,我需要一个项目数组。我想知道哪一个最快/最好使用(在c中),我将做以下事情:

  • 在末尾添加元素
  • 在开始时删除元素
  • 查看第一个和最后一个元素(每帧)
  • 偶尔清理一下
  • 将其转换为普通数组(不是列表。我正在使用iTween,它要求一个普通数组。)我几乎每一帧都会这样做
  • 那么,考虑到这些事情,什么才是最好的选择呢?特别是最后一个,因为我每一帧都在做。我应该只使用数组,还是有其他东西可以非常快速地转换为数组,并且在开始和结束时可以轻松地添加/删除元素?

    您可以看看

    它支持在开始或结束时检查、添加和删除项目。复制到数组需要O(n),但这似乎是不可避免的。如果您使用的API接受了
    i集合
    i可数
    ,则可以避免复制,但如果无法更改,则您可能会坚持使用
    ToArray

    如果列表每帧更改少于一次,则可以缓存阵列,并且仅在列表自上一帧更改后再次调用
    ToArray
    。下面是一些方法的实现,让您了解这种潜在优化的工作原理:

    private LinkedList<T> list = new LinkedList<T>();
    
    private bool isDirty = true;
    
    private T[] array;
    
    public void Enqueue(T t)
    {
        list.AddLast(t);
        isDirty = true;
    }
    
    public T[] ToArray()
    {
        if (isDirty) 
        {
            array = list.ToArray();
            isDirty = false;
        }
    
        return array;
    }
    
    private LinkedList=new LinkedList();
    private bool isDirty=true;
    私有T[]数组;
    公共无效排队(T)
    {
    list.AddLast(t);
    isDirty=true;
    }
    公共T[]ToArray()
    {
    如果(isDirty)
    {
    array=list.ToArray();
    isDirty=false;
    }
    返回数组;
    }
    
    要求1)和2)指向一个
    队列
    ,它是为这两个操作优化的唯一标准集合

    3) 要获取最后一个元素,您需要一些技巧,首先是
    Peek()

    4) 很简单(
    .Clear()

    5) 标准的
    .ToArray()
    方法将完成此操作


    您将无法避免复制所有元素(
    O(n)
    )项5)

    圆形数组如何?如果保留最后一个元素和第一个元素的索引,那么对于给定的每个条件,都可以有O(1)


    编辑:你可以用C++矢量方法来处理容量:当它满的时候,它的大小是一倍。

    正则表将完成这项工作,它比插入的更快。

    • 在末尾添加元素->myList.Insert(myList.Count-1)
    • 从开始处删除元素->myList.RemoveAt(0)
    • 查看第一个和最后一个元素(每帧)->myList[0]或 myList[myList.Count-1]
    • 偶尔清除->myList.Clear()
    • 将其转换为普通数组(不是列表。我正在使用iTween和it 问一个普通数组。)我几乎每帧都会这样做。-> myList.ToArray()

    我假设您使用的是类(而不是结构)?(如果您使用的是structs(值类型),那么这会稍微改变一些情况。)

    这门课可以让你快速完成所有这些。使用LinkedList可以做得更好的唯一部分是从一开始就删除,但单块内存拷贝不会带来太多麻烦,而且它可以轻松创建阵列

    我不建议使用链表,尤其是如果您只是从开始或结束处删除。每次添加(使用标准LinkedList集合)都需要内存分配(它必须构建一个对象来引用实际要添加的内容)

    列表还有很多方便的函数,如果性能有问题,在使用时需要小心。列表本质上是数组,当您添加内容时,它们会变得更大(每次填充过多,它们会变得更大,从而节省过多的内存操作)。清除它们不需要任何努力,并且将内存分配给另一天使用

    根据个人经验,.NET不适用于一般的链表,您需要专门编写代码来处理它们。清单:

    • 很容易使用

    • 做你想做的一切

    • 不会让您的内存看起来像瑞士奶酪(好吧,当您在每一帧分配一个新数组时,您所能做的最好的事情就是这样做——我建议您在创建新数组之前给垃圾收集器一个机会,如果这些数组通过重新使用任何数组引用并将不需要的任何数组置零而变得很大,那么在创建新数组之前,您可以让垃圾收集器清除所有旧数组)

    正确的选择在很大程度上取决于应用程序的具体情况,但如果您问我,列表始终是一个安全的赌注,并且您不必编写任何特定于结构的代码来让它工作

    如果您确实想使用列表,您需要查看以下内容:

    • ToArray()//生成所需的数组

    • Clear()//清除数组

    • 添加(项)//将项添加到末尾

    • RemoveAt(index)//第一项为索引0,最后一项为计数-1

    • Count//检索列表中的项目数-这不是免费查找,因此请尝试避免不必要的请求


    很抱歉,这篇文章写得太过火了。

    我冒昧地将项目符号改为数字,这样更便于参考。@HenkHolterman思考得好!你能再解释一下吗?特别是如何增加容量。取决于数组必须以何种形状/形式生成。System.Collections.Generic.List基本上是一个std::vector。但是
    RemoveAt(0)
    将是
    O(n)
    。这似乎是可以避免的。@Henkholtman我很抱歉,但这很有趣。0(n)表示什么?@AdilMammadov O(n)表示操作所需的时间与n(项目数)成正比。因此,如果将列表的长度增加一倍,则操作所需的时间将增加一倍。相比之下,O(1)运算不依赖于列表的长度,因此当列表变大时,运算速度要快得多。@IanGoldby,4年多过去了,