【0】README
1)本文旨在给出 推排序的源码实现;堆排序是基于二叉树的数组实现的;
【1】堆排序步骤
step1)对排序数据建堆,执行 n 次 insert 操作(基于上滤操作);每次 insert 包括 将 新元素插入到堆末尾,然后执行 上滤操作;step2)执行 n 次 deleteMin 操作(基于下滤操作),每一次 deleteMin 操作都包含 将 堆的根元素 和 堆最后一个元素交换,并对根 执行 下滤操作;step3)经过 deleteMin 操作后, 堆所在的数组中的元素是 逆序的;
Conclusion)由此可见,堆排序的关键操作是 上滤操作 和 下滤操作;
【2】源码实现(for full source code, please visit https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter7/review/p170_heap_sort )
1)insert插入操作(基于上滤操作)
// 插入操作 based on 上滤操作.
void insert(BinaryHeap heap, ElementType data)
{if(heap->size == heap->capacity-1){Error("failed insert() for heap is full.");} percolateUp(heap, data);
}// 上滤操作(key operation)
void percolateUp(BinaryHeap heap, ElementType data)
{int i;// 必须将size++.for(i=++heap->size; data < heap->array[i/2]; i/=2){heap->array[i] = heap->array[i/2];}heap->array[i] = data;
}
2)deleteMin操作(基于下滤操作)
// delete minimal from heap based on percolateDown().
void deleteMin(BinaryHeap heap)
{ if(heap->size==0){Error("failed deleteMin() for the heap is empty");return ;} swap(&heap->array[1], &heap->array[heap->size--]); // 将二叉堆的根和二叉堆的最后一个元素交换,size--。percolateDown(heap, 1); // 执行下滤操作.
}// 下滤操作(key operation)
void percolateDown(BinaryHeap heap, int i)
{int child;int temp; for(temp=heap->array[i]; (child=leftChild(i))<=heap->size; i=child){ if(child<heap->size && heap->array[child] > heap->array[child+1]){child++;}if(temp > heap->array[child]) // 比较是和 temp=heap->array[index] 进行比较.{ heap->array[i] = heap->array[child];}else{ break;}}heap->array[i] = temp;
}int leftChild(int index)
{return 2*index;
}// swap a and b.
void swap(ElementType* a, ElementType* b)
{ElementType t;t = *a;*a = *b;*b = t;
}
对以上代码的分析(Analysis):(最难实现的就是 下滤操作)
A1)第21行 的 child<heap->size 是必须需要的,不要认为 它 和 第19行的 (child=leftChild(i))<=heap->size 雷同了,因为有可能 该节点只有左孩子,而没有右孩子;A2)如下图所示,size=4的堆:节点53就只有左孩子而没有右孩子,所以第21行是不需要执行的,这通过 child<heap->size 来控制;