我想将int插入到已排序的数组中。此操作将经常执行,因此需要尽可能快。
我在考虑许多不同的方法,包括二进制搜索和简单的插入复制,但发现很难做出决定。而且,我觉得我错过了一个主意。您是否有关于此主题的经验或要考虑的任何新想法?
答案 0 :(得分:3)
我将使用长度为35的int数组(因为你说的范围是1-34)来记录数字的状态。
int[] status = Enumerable.Repeat(0, 35).ToArray();
//an array contains 35 zeros
//which means currently there is no elements in the array
status[10] = 1; // now the array have only one number: 10
status[11] ++; // a new number 11 is added to the list
因此,如果您想在列表中添加数字i:
status[i]++; // O(1) to add a number
要从列表中删除i:
status[i]--; // O(1) to remove a number
想知道列表中的所有数字吗?
for (int i = 0; i < status.Length; i++)
{
if (status[i] > 0)
{
for (int j = 0; j < status[i]; j++)
Console.WriteLine(i);
}
}
//or more easier using LINQ
var result = status.SelectMany((i, index) => Enumerable.Repeat(index, i));
以下示例可帮助您更好地理解我的代码:
the real number array: 1 12 12 15 9 34 // i don't care if it's sorted
the status array: status[1]=1,status[12]=2,status[15]=1,status[9]=1,status[34]=1
all others are 0
答案 1 :(得分:2)
在14个值处,这是一个相当小的数组,我不认为切换到更智能的数据结构(如列表)会赢得很多,特别是如果你快速好随机访问。甚至二进制搜索实际上可能比这种规模的线性搜索慢。您是否确定,例如,insert-on-copy不能满足您的性能要求?
答案 2 :(得分:1)
此操作将经常执行,因此需要尽可能快。
你经常发现的事情经常发生在不程序中的瓶颈 - 实际的瓶颈往往令人惊讶。在执行任何优化之前,您应该编写简单的代码并测量程序的实际性能。
我在考虑许多不同的方法,包括二进制搜索和简单的插入复制,但发现很难做出决定。
假设这是瓶颈,不同方法的大O性能在这里并不重要,因为阵列的体积很小。只需尝试几种不同的方法,测量结果,查看哪种方法效果最好并选择该方法就更容易了。如果您已按照第一段中的建议操作,那么您已经拥有了可用于此步骤的探查器设置。
答案 3 :(得分:1)
要插入中间,LinkedList<int>
将是最快的选项 - 其他任何内容都涉及复制数据。在14个元素中,不要强调二元搜索等 - 只需向前走到你想要的项目:
using System;
using System.Collections.Generic;
static class Program
{
static void Main()
{
LinkedList<int> data = new LinkedList<int>();
Random rand = new Random(12345);
for (int i = 0; i < 20; i++)
{
data.InsertSortedValue(rand.Next(300));
}
foreach (int i in data) Console.WriteLine(i);
}
}
static class LinkedListExtensions {
public static void InsertSortedValue(this LinkedList<int> list, int value)
{
LinkedListNode<int> node = list.First, next;
if (node == null || node.Value > value)
{
list.AddFirst(value);
}
else
{
while ((next = node.Next) != null && next.Value < value)
node = next;
list.AddAfter(node, value);
}
}
}
答案 4 :(得分:0)
这里做蛮力方法是最好的决定,因为14不是数字:)。但是,这不是一个可扩展的决定,因为应该14天会变成14000,这将导致问题
答案 5 :(得分:0)
您的阵列最常见的操作是什么? 插入?读?
顺便问一下,您是否尝试过System.Collections.Generic.SortedDictionary ot System.Collections.Generic.SortedList?
答案 6 :(得分:0)
如果你在.Net 4上,你应该看一下SortedSet<T>
。否则,请查看SortedDictionary<TKey, TValue>
,将TValue
作为object
,然后将null
放入其中,因为您只对密钥感兴趣。
答案 7 :(得分:0)
如果数组上没有重复值且可能的值不会改变,则可能是固定大小的数组,其中值等于索引是一个不错的选择
插入和读取都是O(1)
答案 8 :(得分:0)
您有一系列可能的值,从1-34开始,相当窄。因此,最快的方法可能是使用具有34个插槽的阵列。要插入一个数字n,只需执行数组[n-1] +并删除它,执行数组[n.1] - (如果n> 0)。
要检查集合中是否存在值,请执行数组[n-1]&gt; 0。
编辑:该死... Danny更快。 :)
答案 9 :(得分:0)
编写一个方法获取一个整数数组,并使用冒泡排序对它们进行排序。不允许该方法创建任何其他数组。冒泡排序是一种简单的排序算法,它通过循环遍历要排序的数组,比较每对相邻元素并交换它们,如果它们的顺序错误。