计算堆排序对数组进行排序所需的步骤数

时间:2018-03-31 15:10:05

标签: c# algorithm sorting heap heapsort

所以我一直在玩着#34;着名的"排序算法,以查看它们对数组进行排序的步骤。但是我被困在Heapsort上,我无法弄清楚如何正确计算步数。通过我的实现,对128个长数组进行排序平均需要630步 - 这比nlog(n)要多得多。使用quicksort对相同的数组进行排序时,它大约是260-280,这几乎就是nlogn,这告诉我heapsort的计数器是错误的。这是我目前的代码:

    public static int heapify(double[] heap, int size, int index, bool asc, int steps)
    {
        int left = (index + 1) * 2 - 1;
        int right = (index + 1) * 2;
        int largest = 0;
        int stepCounter = steps;
        //For ascending sorting
        //Note: ideally there should be a maxHeapify for ascending and minHeapify for descending sorting seperately
        //however in this case it is easy to see what is happening
        if(asc)
        {
            if (left < size && heap[left] > heap[index])
            {
                largest = left;
            }
            else
            {
                largest = index;
            }

            if (right < size && heap[right] > heap[largest])
            {
                largest = right;
            }
        } else
        {//For descending sorting
            if (left < size && heap[left] < heap[index])
            {
                largest = left;
            }
            else
            {
                largest = index;
            }

            if (right < size && heap[right] < heap[largest])
            {
                largest = right;
            }
        }

        if (largest != index)
        {
            double temp = heap[index];
            heap[index] = heap[largest];
            heap[largest] = temp;
            stepCounter++;
            stepCounter = heapify(heap, size, largest, asc, stepCounter);
        }
        return stepCounter;
    }
    public static void heapSort(double[] heap, bool asc, int steps = 0)
    {
        int size = heap.Length;
        int i;
        int stepCounter = steps;
        //Build heap
        for (i = (size - 1) / 2; i >= 0; i--)
        {
            stepCounter = heapify(heap, size, i, asc, stepCounter);
        }

        for(i = heap.Length - 1; i > 0; i--)
        {
            double temp = heap[i];
            heap[i] = heap[0];
            heap[0] = temp;
            size--;
            stepCounter = heapify(heap, size, 0, asc, stepCounter);
        }
        Console.WriteLine("Heap sort has taken {0} steps", stepCounter);
    }

感谢。 需要说明的是:我最后只需要一个语句,打印所有步骤的数量,而不是大量的消息,每个步骤2-3步。

编辑: 我像这样改变了代码:

    public static int heapify(double[] heap, int size, int index, bool asc, int steps)
    {

        int stepCounter = 0;

        if (largest != index)
        {
            double temp = heap[index];
            heap[index] = heap[largest];
            heap[largest] = temp;
            stepCounter++;
            heapify(heap, size, largest, asc, stepCounter);
        }
        return stepCounter;
    }
    public static void heapSort(double[] heap, bool asc, int steps = 0)
    {
        int stepCounter = steps;
        //Build heap
        for (i = (size - 1) / 2; i >= 0; i--)
        {
            stepCounter += heapify(heap, size, i, asc, stepCounter);
        }

        for(i = heap.Length - 1; i > 0; i--)
        {
            double temp = heap[i];
            heap[i] = heap[0];
            heap[0] = temp;
            size--;
            stepCounter += heapify(heap, size, 0, asc, stepCounter);
        }
        Console.WriteLine("Heap sort has taken {0} steps", stepCounter);
    }

(删除不相关的位)。有了这个,我平均得到128个长度数组160-170,长度约1000个数组约1300步。我认为这听起来很合理。谢谢@jdweng

1 个答案:

答案 0 :(得分:4)

但是我被困在Heapsort上,我无法弄清楚如何正确计算步数。通过我的实现,对128个长数组进行排序平均需要630步 - 这比nlog(n)要多得多。使用quicksort对相同的数组进行排序时,它大约是260-280,这几乎就是nlogn,这告诉我heapsort的计数器是错误的。

这段经文表明你不懂大O符号。

当我们说f(n) = O(g(n))时,我们的意思是存在常量kN,如果N < n那么|f(n)| < k |g(n)|。换句话说,&#34;增长模式并不比g(n)&#34;更差。它没有提到常数。而对于小数字的表现一无所知。

现在heapsort和quicksort都是O(n log(n))。但是它们有不同的常数。 Quicksort得名,因为它平均比mergesort和quicksort等替代品快得多。你看到的恒定差异反映了这一点。

但是,我会在n上收集有关多个值的数据并生成图f(n)/(n log(n))