如何快速将int插入排序数组?

时间:2010-11-18 12:25:00

标签: c# .net arrays performance copy

我想将int插入到已排序的数组中。此操作将经常执行,因此需要尽可能快。

  • 甚至可以使用List或任何其他类而不是数组
  • 所有值均在1到34范围内
  • 数组通常包含14个值

我在考虑许多不同的方法,包括二进制搜索和简单的插入复制,但发现很难做出决定。而且,我觉得我错过了一个主意。您是否有关于此主题的经验或要考虑的任何新想法?

10 个答案:

答案 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)

您的阵列最常见的操作是什么? 插入?读?

  • 堆数据结构将为您提供O(log(14))。 SortedDictionary可能会影响您的表现。
  • 使用简单的数组会给你O(1)进行阅读,O(14)进行插入。

顺便问一下,您是否尝试过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)

编写一个方法获取一个整数数组,并使用冒泡排序对它们进行排序。不允许该方法创建任何其他数组。冒泡排序是一种简单的排序算法,它通过循环遍历要排序的数组,比较每对相邻元素并交换它们,如果它们的顺序错误。