找到更高效的堆排序?

时间:2016-03-06 00:32:25

标签: java sorting complexity-theory heapsort

目前我有一个家庭工作问题,

  

可以通过以下方式提高堆排序算法的效率   编写一个方法,一次命令整个列表而不是   一次添加一个元素。

但是我无法弄清楚它是什么意思“而不是一次添加一个元素”,当然必须首先构建一个堆(这涉及逐个添加未排序列表中的元素),然后删除一次一个堆中最大的。

这是我的堆数组:

import exceptions.exceptions.*;

public class ArrayHeap<T> extends ArrayBinaryTree<T> implements HeapADT<T> {

    public ArrayHeap(){
        super();
    }

    public void addElement (T element){
        if (count==size())
            expandCapacity();
        tree[count] = element;
        count++;
        if (count > 1)
            heapifyAdd();
    }

    private void heapifyAdd(){
        int index = count - 1;
        while ((index != 0) && (((Comparable)tree[index]).compareTo(tree[(index-1)/2]) < 0))
        {
            T temp = tree[index];
            tree[index] = tree[(index-1)/2];
            tree[(index-1)/2] = temp;
            index = (index-1)/2;
        }
    }

    public T removeMin(){
        if (isEmpty())
            throw new EmptyCollectionException ("Empty Heap");
        T minElement = findMin();
        tree[0] = tree[count-1];
        heapifyRemove();
        count--;
        return minElement;
    }

    private void heapifyRemove()
    {
        T temp;
        int node = 0;
        int left = 1;
        int right = 2;
        int next;

        if ((tree[left] == null) && (tree[right] == null))
           next = count;
        else if (tree[left] == null)
           next = right;
        else if (tree[right] == null)
           next = left;
        else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
           next = left;
        else
           next = right;
        while ((next < count) && (((Comparable)tree[next]).compareTo(tree[node]) < 0)){
                temp = tree[node];
                tree[node] = tree[next];
                tree[next] = temp;
                node = next;
                left = 2*node + 1;
                right = 2*(node+1);
                if ((tree[left] == null) && (tree[right] == null))
                   next = count;
                else if (tree[left] == null)
                   next = right;
                else if (tree[right] == null)
                   next = left;
                else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
                   next = left;
                else
                   next = right;
            }
    }

    public T findMin() {
        if (isEmpty())
           throw new EmptyCollectionException ("Empty Heap");
        return tree[0];
    }
}

以下是更多HeapSort算法:

import ArrayHeap;

public class HeapSort<T>{

    public T[] heapsort(T[] data, int min, int max){
        ArrayHeap<T> temp = new ArrayHeap<T>();
        for (int c = min; c <= max; c++){
            temp.addElement(data[c]);
        }
        int count = min;
        while(!(temp.isEmpty())){
            T jj = temp.removeMin();
            data[count] = jj;
            count ++;
        }
        return data;
    }

1 个答案:

答案 0 :(得分:2)

执行heapsort最直接的方法是使用单独的堆并将所有元素添加到它中,然后当我们逐个弹出它们时,元素将按顺序排列。这就是&#34;一次添加一个元素&#34;在语句中引用,这就是你的实现正在做的事情:创建一个类型ArrayHeap的堆并向其插入data的元素,最后将元素弹回到{{1} }。

一种更有效的方式(在空间和时间方面)是执行就地排序,我们使用数组作为堆进行排序,而不是使用额外的内存堆,这就是&#34;一次订购整个清单&#34;是指。这个实现的步骤如下,我们将按非递减顺序对元素进行排序:

  1. 我们 max-heapify 输入数组(即我们重新排列数组中的元素,使其遵循max-heap属性。
  2. 对于data = n - 1到1:
    1. 使用i元素交换数组中的0个元素。
    2. 将堆的大小减小1(即堆的大小应为i)。
    3. 在堆上执行i操作以恢复最大堆属性。
  3. 请注意,只要max-heap属性成立,堆中最顶层的元素就是最大的元素,所以在sift-down - 迭代的开始(k这里){ {1}} - 元素是k = n - i - 最大元素,我们通过交换放置在数组中的正确位置。

    请注意,步骤1可以在0中完成,在步骤2中有k次迭代,每次O(n)操作需要时间O(n),因此整体时间复杂度是sift-down

    以下是Java实现,供您参考:

    O(log(n))