/*
* 选择排序之堆排序
* 按照完全二叉树的顺序存储方式,建立一颗完全二叉树
* 若是大根堆:l(i)>=l(2*i),l(i)>=l(2*i+1)
* 若是小根堆:l(i)<=l(2*i),l(i)<=(2*i+1)
* 此时,初始堆建成,接下来的工作是进行调整
* 调整的是从[n/2]~1。
* 针对大根堆:对于[n/2]处的元素,若其比左右孩子中的较大者小,进行交换
* 同理对于其他的
* void BuildHeap(ET a[],int len){
* for(int i=n/2;i>0;i--){
* AdjustDown(a[],i,len);
* }
* void AdjustDown(ET a[],int k,int len){
* a[0]=a[k];
* for(i=2*k;i<=len;i=i*2){
* if(i<len&&a[i]<a[i+1])
* i++;
* if(a[0]>a[i])
* break;//排序成功,跳出循环
* else{
* a[k]=a[i];//a[i]向上翻,反正a[k]的值已经赋出去了,有了本分
* k=i; //同时新的待排序的k就是i,要继续向下继续调整
* }
* }
* a[k]=a[0];//最终的位置
* }
* 下面要说的是完整的堆排序过程
* 在建成一个真正意义上的对之后,我们还需要将其输出,这样我们才能直观的看到算法处理的结果
* 而堆排序的输出,通常是输出堆顶元素后,通常将堆底元素送入堆顶,但此时肯定是不满足堆的性质的,
* 所以此时必要又要重新调整堆,待调整完毕后,在进行输出,循环如此
* void HeapSort(ET a[],int len){
* BulidHeap(a,len);
* for(i=len;i>1;i--){
* print(a[1]);//输出堆顶元素
* swap(a[len],a[1]);//将最后堆底元素换到堆顶
* AdjustDown(a,1,len-1);//输出一个元素后,还剩len-1
*
* }
*
* }
堆排序的时间复杂度跟最终形成的树形状有关
建堆时间是O(n),之后进行n-1次的调整(在建造堆的时候有一半,而在输出的时候又有一半?),每次调整的时间与树的高度有关,那就是O(h),又因是完全二叉树,所以最终的时间复杂度为O(nlogn)
*
* }
*/