2.4.39

2.4.39 #

解答 #

结果如下,约占总耗时的 2~5%。

代码 #

var random = new Random();
Console.WriteLine("number\tBuild\tSort\tRatio");
var n = 1000; // 当数据量到达 10^9 时会需要 2G 左右的内存
var multiTen = 7;
for (var i = 0; i < multiTen; i++)
{
    var data = GetRandomArray(n);
    var fullSort = new Stopwatch();
    var buildHeap = new Stopwatch();

    fullSort.Restart();

    buildHeap.Restart();
    BuildHeap(data);
    buildHeap.Stop();

    HeapSort(data);
    fullSort.Stop();

    var buildTime = buildHeap.ElapsedMilliseconds;
    var fullTime = fullSort.ElapsedMilliseconds;
    Console.WriteLine(n + "\t" + buildTime + "\t" + fullTime + "\t" + (double)buildTime / fullTime);
    n *= 10;
}

short[] GetRandomArray(int number)
{
    var data = new short[number];
    for (var i = 0; i < number; i++)
    {
        data[i] = (short)random.Next();
    }

    return data;
}

// 将数组构造成堆。
void BuildHeap(short[] data)
{
    var count = data.Length;
    for (var k = count / 2; k >= 1; k--)
    {
        Sink(data, k, count);
    }
}

// 利用已经生成的堆排序。
void HeapSort(short[] heap)
{
    var count = heap.Length;
    while (count > 1)
    {
        Exch(heap, 1, count--);
        Sink(heap, 1, count);
    }
}

// 令堆中的元素下沉。
void Sink(short[] pq, int k, int number)
{
    while (2 * k <= number)
    {
        var j = 2 * k;
        if (j < number && Less(pq, j, j + 1))
            j++;
        if (!Less(pq, k, j))
            break;
        Exch(pq, k, j);
        k = j;
    }
}

// 比较堆中下标为 a 的元素是否小于下标为 b 的元素。
static bool Less(short[] pq, int a, int b) => pq[a - 1].CompareTo(pq[b - 1]) < 0;

// 交换堆中的两个元素。
static void Exch(short[] pq, int a, int b)
{
    var temp = pq[a - 1];
    pq[a - 1] = pq[b - 1];
    pq[b - 1] = temp;
}

另请参阅 #

PriorityQueue 库