堆排序(怎么构造堆,在堆排序过程中的比较方法)
堆排序(如何构造堆,在堆排序过程中的比较方法)
题目:无序序列{59,11,26,34,17,91,25},要用堆排序得到{11,17,25},共执行多少次比较?
我的问题是:如何从无序序列构造堆?
我用的是清华严蔚敏的教材,上面说:'从一个无序序列建堆的过程就是一个反复"筛选"的过程.'
而从书上又可以了解到"筛选"是作用于二叉树的操作,这棵二叉树是从哪来的呢,书上给的例子也是直接就有一棵二叉树,这点我不太理解.如果说这棵二叉树是通过一定的规则构造的,那么我的问题是:如何从一组无序序列构造堆所对应的二叉树呢?
就以上面的无序序列作为例子吧.
------解决方案--------------------
通过建堆算法。
也就是建立你说的“书上给的例子也是直接就有一棵二叉树”的那棵二叉树。这是堆排序的先决条件。只有无序序列已经是堆了,用堆排序算法才可以起到排序的效果。建堆算法应该在前面已经出现了,所以作者才直接给出了无序序列的堆形式(也就是那棵二叉树)。
------解决方案--------------------
题目:无序序列{59,11,26,34,17,91,25},要用堆排序得到{11,17,25},共执行多少次比较?
我的问题是:如何从无序序列构造堆?
我用的是清华严蔚敏的教材,上面说:'从一个无序序列建堆的过程就是一个反复"筛选"的过程.'
而从书上又可以了解到"筛选"是作用于二叉树的操作,这棵二叉树是从哪来的呢,书上给的例子也是直接就有一棵二叉树,这点我不太理解.如果说这棵二叉树是通过一定的规则构造的,那么我的问题是:如何从一组无序序列构造堆所对应的二叉树呢?
就以上面的无序序列作为例子吧.
------解决方案--------------------
通过建堆算法。
也就是建立你说的“书上给的例子也是直接就有一棵二叉树”的那棵二叉树。这是堆排序的先决条件。只有无序序列已经是堆了,用堆排序算法才可以起到排序的效果。建堆算法应该在前面已经出现了,所以作者才直接给出了无序序列的堆形式(也就是那棵二叉树)。
------解决方案--------------------
- C/C++ code
#define PARENT(i) ((i) / 2) #define LEFT(i) ((i) * 2) #define RIGHT(i) ((i) * 2 + 1) #define RELOCAL(i) ((i) - 1) template <class T> void MaxHeapify(T *array,const size_t length,const size_t i) { if (NULL == array || length == 0 || 0 == i || i > length) { return; } if (LEFT(i) <= length) { if(array[RELOCAL(i)] < array[RELOCAL(LEFT(i))]) { Swap(array[RELOCAL(i)],array[RELOCAL(LEFT(i))]); } } if (RIGHT(i) <= length) { if (array[RELOCAL(i)] < array[RELOCAL(RIGHT(i))]) { Swap(array[RELOCAL(i)],array[RELOCAL(RIGHT(i))]); } } MaxHeapify(array,length,LEFT(i)); MaxHeapify(array,length,RIGHT(i)); return; } template <class T> void BuildMaxHeap(T *array,const size_t length) { if (array == NULL || length <= 1) { return; } size_t i = length/2; while (i != 0) { MaxHeapify(array,length,i); --i; } return; } template <class T> void HeapSort(T *array,const size_t length) { if (array == NULL || length <= 1) { return; } BuildMaxHeap(array,length); size_t l = length; while (l != 0) { swap(array[0],array[RELOCAL(l)]); --l; MaxHeapify(array,l,1); } return; }
------解决方案--------------------
debug.h
- C/C++ code
class OutOfBounds { };
------解决方案--------------------
建堆思想:
首先将无序序列一次作为一个完全二叉树存储,也就是你上面的例子中59作为根,依次11,26作为孩子节点等等延续。
然后从第n/2个节点开始,一直到第一个节点59,进行堆的调整,这个过程叫建堆。
如果是大根堆,那么第一个元素就是最大的节点,取出最大节点和最后一个节点元素交换,然后堆的大小相应减1,然后从根开始调整堆!!