C#Collection – 按元素排序(旋转)
我有一个IEnumerable
集合。 可以说它包含5个点(实际上它更像2000)
我想订购这个集合,以便集合中的特定点成为第一个元素,因此它基本上是在特定点切割集合并将它们重新连接在一起。
所以我的5点清单:
{0,0}, {10,0}, {10,10}, {5,5}, {0,10}
关于索引3处的元素重新排序将变为:
{5,5}, {0,10}, {0,0}, {10,0}, {10,10}
解决这个问题的计算效率最高的方法是什么,或者是否存在已经存在的内置方法……如果是这样,我似乎找不到一个!
var list = new[] { 1, 2, 3, 4, 5 }; var rotated = list.Skip(3).Concat(list.Take(3)); // rotated is now {4, 5, 1, 2, 3}
在这种情况下,一个简单的数组副本就是O(n),它应该足以满足几乎所有的实际用途。 但是,我会授予您在某些情况下 – 如果这是多级算法的深层内容 – 这可能是相关的。 此外,您是否只需要以有序的方式遍历此集合或创建副本?
链接列表很容易像这样重新组织,尽管访问随机元素会更加昂贵。 总体而言,计算效率还取决于您访问此项集合的准确程度(以及它们是什么类型的项目 – 值类型或引用类型?)。
标准的.NET链表似乎不支持这样的手动操作,但一般来说,如果你有一个链表,你可以按照你描述的方式轻松移动列表的各个部分,只需指定新的“next”和“previous” “指向端点的指针。
此处提供的集合库支持此function: http : //www.itu.dk/research/c5/ 。 具体来说,您正在寻找LinkedList
方法,您可以对LinkedList
返回的对象使用该方法。
版本没有枚举list
两次,但由于T[]
而导致内存消耗较高:
public static IEnumerable Rotate (IEnumerable source, int count) { int i = 0; T[] temp = new T[count]; foreach (var item in source) { if (i < count) { temp[i] = item; } else { yield return item; } i++; } foreach (var item in temp) { yield return item; } } [Test] public void TestRotate() { var list = new[] { 1, 2, 3, 4, 5 }; var rotated = Rotate(list, 3); Assert.That(rotated, Is.EqualTo(new[] { 4, 5, 1, 2, 3 })); }
注意:添加参数检查。
ulrichb显示的Linq方法的另一种替代方法是使用Queue Class(一个fifo集合)出列到你的索引,并将你已经取出的那些排队。
使用linq的天真实现将是:
IEnumerable x = new[] { 1, 2, 3, 4 }; var tail = x.TakeWhile(i => i != 3); var head = x.SkipWhile(i => i != 3); var combined = head.Concat(tail); // is now 3, 4, 1, 2
这里发生的是你执行两次比较所需的比较,以达到组合序列中的第一个元素。 该解决方案可读且紧凑,但效率不高。 其他贡献者描述的解决方案可能更有效,因为它们使用特殊数据结构作为数组或列表。
上述就是C#学习教程:C#Collection – 按元素排序(旋转)分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1034481.html