简体   繁体   English

维护排序顺序C#的集合

[英]Collection that maintains sort order C#

I have a class Foo which contains a list of objects: List<Bar> . 我有一个类Foo ,它包含一个对象List<Bar>List<Bar> Each Bar has a property which they can be ordered on (of type TimeSpan , representing a duration), and Bar is an immutable object - that is, the duration does not change over the running of the algorithm. 每个Bar都有一个可以订购的属性( TimeSpan类型,表示持续时间), Bar是一个不可变对象 - 也就是说,持续时间不会因算法的运行而改变。 At the moment, for each Foo I also maintain the Bar that would be first in the list if it were to be ordered (ie the Bar of shortest duration). 目前,对于每一个Foo我还保持Bar ,这将是第一个在列表中,如果它是被命令(即Bar最短持续时间)。 Something like this: 像这样的东西:

public class Foo
{
    public List<Bar> AllBars { get; set; }

    public Bar FirstBar { get; set; }

    public Foo (Bar bar)
    {
        FirstBar = bar;

        AllBars = new List<Bar>() { bar };
    }

    public AddBar(Bar bar)
    {
        if(bar.Duration < FirstBar.Duration)
        {
            FirstBar = bar;
        }

        AllBars.Add(bar);
    }
}

This class Foo is used in an algorithm where processing performance (speed) is critical. 此类Foo用于处理性能(速度)至关重要的算法中。 Memory is important but not as much as speed. 记忆很重要但不如速度快。 There is a list of n Foo s, each of which has up to m Bar s. 有一个n Foo列表,每个都有最多m Bar This class has served me well up until this point. 直到这一刻,这门课一直很好。 I now wish to offer the user several choices, meaning I will need to provide random access to the first few Bar s in the list. 我现在希望为用户提供多种选择,这意味着我需要提供对列表中前几个Bar的随机访问。

I would thus like to store my Bar s in order so that I can access them by index in order. 因此,我想按顺序存储我的Bar ,以便我可以按顺序访问它们。 In my Bar class I implemented IComparable to allow Bar s to be compared on duration but I am stuck at choosing an appropriate data type. 在我的Bar类中,我实现了IComparable以允许在持续时间上比较Bar ,但我坚持选择合适的数据类型。 I looked at System.Collections.SortedList but (unless I am wrong) this appears to reference elements by key as it implements IDictionary . 我查看了System.Collections.SortedList但是(除非我错了)这似乎是按键引用元素,因为它实现了IDictionary What collection could I use that would maintain my objects such that they stay sorted, and such that they are traversable in order of index? 我可以使用哪些集合来维护我的对象,使它们保持排序状态,并且它们可以按索引顺序遍历?

I prefer to use SortedSet<T> , which is a binary tree where the key and value are the same object. 我更喜欢使用SortedSet<T> ,它是一个二叉树,其中键和值是同一个对象。 This once again means that adding/removing/lookups are logarithmic - O(log n) - but you gain the ability to iterate over the items in order. 这再次意味着添加/删除/查找是对数的 - O(log n) - 但您可以按顺序迭代项目。 For this collection to be effective, type T must implement IComparable<T> or you need to supply an external IComparer<T> . 要使此集合生效,类型T必须实现IComparable<T>否则您需要提供外部IComparer<T>

Why not just use List.Insert ? 为什么不直接使用List.Insert
Insert is O(n) and lets you insert at a specific index. Insert是O(n),允许您插入特定索引。
n + n is still O(n) n + n仍为O(n)

public AddBar(Bar bar)
{
    int index = 0;    
    foreach (bar b in AllBar)
    {
       if(bar.Duration < b.Duration)
         break;
       index++;
    }
    AllBars.Insert(index, bar);
}

So you have sort and O(1) index 所以你有排序和O(1)索引
At a cost of O(n) Add 以O(n)加成本为代价
The current Add in also O(n) 当前加入也是O(n)

A SortedList in NlogN and then you don't have index as the key is Duration and the key in not unique NlogN中的SortedList,然后您没有索引,因为密钥是持续时间,密钥不唯一

A SortedSet insert is LogN but a ToList is O(n) so you are still O(n) SortedSet插入是LogN但是ToList是O(n)所以你仍然是O(n)

Calling the the Sort method on the list is NlogN 在列表上调用Sort方法是NlogN

This answers the stated question of: What collection could I use that would maintain my objects such that they stay sorted, and such that they are traversable in order of index? 这回答了所陈述的问题: 我可以使用哪些集合来维护我的对象,使它们保持排序,并且它们可以按索引顺序遍历?

I don't think you are going to do that with better than O(n) Add. 我不认为你会比O(n)添加更好。
Who ever gave it a down vote then what is a better solution? 谁给了它一个投票然后什么是更好的解决方案?

(promoted from a comment, as requested by the asker) (根据提问者的要求从评论中提升)

If you can live with having "values" that mean nothing, just use a SortedList<Bar, object> where you do not use the value part. 如果你可以忍受没有任何意义的“值”,只需使用一个SortedList<Bar, object> ,你不使用值部分。

Add with yourSortedList.Add(yourBar, null) in O(n) time (the list will have to move "up" all entries after the point where you insert). 在O(n)时间内使用yourSortedList.Add(yourBar, null)添加(列表必须在插入点之后“向上”移动所有条目)。 Retrieve the i th entry in O(1) time with yourSortedList.Keys[i] . 使用yourSortedList.Keys[i]在O(1)时间内检索第i个条目。

See the SortedList<,>.Keys property documentation for some "proof" that the above description is correct. 有关上述描述正确的“证据”,请参阅SortedList<,>.Keys属性文档 Note that a SortedList<,> actually consists of a "list" (ie an array of length Capacity , subject to substitution by a larger array when necessary). 请注意, SortedList<,>实际上由一个“列表”组成(即一个长度为Capacity数组,必要时可以用更大的数组替换)。 This is different from SortedDictionary<,> which I believe is a binary search tree. 这与SortedDictionary<,>不同,我认为它是二叉搜索树。

Note however: You will not be able to have duplicates in your SortedList<,> , so two members in the list are not allowed to CompareTo each other with return value zero. 但是请注意:您将不能够有重复你的SortedList<,> ,所以在列表中两个成员是不允许CompareTo彼此返回值为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM