您的位置:首页 > 其它

排序算法-堆排序

2016-06-28 13:50 316 查看
/*

堆排序的基本思想:将所有元素初始化一个最大堆,然后将第一个元素即最大元素与最后一个元素交换;

再对前n-1个元素调整为一个最大堆,就这样依次进行,每次都是把最大元素放到最后边。

*/

void MaxHeapify(int*list,int size,int root)

{

int lChild=2*(root+1)-1,rChild=lChild+1;//根节点的左右孩子节点

while(rChild<size)//如果右孩子节点存在

{

if(list[root]>=list[lChild]&&list[root]>=list[rChild])//如果根节点大于左右孩子节点表明以root为根节点的树已经为最大堆

return;

if(list[lChild]>list[rChild])//如果左孩子大,则选左孩子作为根节点

{

int temp=list[lChild];

list[lChild]=list[root];

list[root]=temp;

root=lChild;

}

else//右孩子大

{

int temp=list[rChild];

list[rChild]=list[root];

list[root]=temp;

root=rChild;

}

lChild=2*(root+1)-1;

rChild=lChild+1;

}

if(lChild<size)//如果只有左孩子存在,说明已到最后

{

if(list[lChild]>list[root])

{

int temp=list[lChild];

list[lChild]=list[root];

list[root]=temp;

}

}

}

//采用迭代实现的堆排序

void HeapSortByIteration(int*list,int size)

{

int last;//最后一个有孩子的节点

if((size-1)%2==0)//该节点既有左孩子,又有右孩子

last=(size-1-2)/2;

else

last=(size-1-1)/2;

for(int i=last;i>=0;i--)//初始化最大堆

MaxHeapify(list,size,i);

while(size>1)

{

//交换根元素和最后一个元素的位置

int temp=list[0];

list[0]=list[size-1];

list[size-1]=temp;

MaxHeapify(list,--size,0);

}

}

//采用递归实现的堆排序存在有失效率的问题,看如下代码

//相当于是每次都要对堆进行一次初始化

void HeapSortByRecursion(int*list,int size)

{

if(size==1)

return;

int last;//最后一个有孩子的节点

if((size-1)%2==0)//该节点既有左孩子,又有右孩子

last=(size-1-2)/2;

else

last=(size-1-1)/2;

for(int i=last;i>=0;i--)//初始化最大堆

MaxHeapify(list,size,i);

//交换根元素和最后一个元素的位置

int temp=list[0];

list[0]=list[size-1];

list[size-1]=temp;

HeapSortByRecursion(list,--size);

}

//堆排序的时间复杂度分析

/*

1.堆排序的时间主要由两部分组成,一部分是建堆时间,另一部分是调整堆的时间。

建堆的时间是O(n),调整堆的时间为O(nlogn)。至于建堆时间可用数学公式进行推导,例如有(1/2)n的元素进行了一次比较,

(1/4)n的元素进行了进行了2次比较,(1/8)n的元素进行了3次比较,....,于是可推出最终的总比较次数O(n);至于调整堆的时间

由于树的高度为log(n),大部分节点都进行了log(n)次的比较,因此时间为O(nlogn)。

2.仔细分析会发现堆排序对于数据的初始顺序状态并不太敏感,即无论初始状态怎么样都要首先建立一个最大堆,所以堆排序的最好最坏的时间

复杂度均为nlog(n)。

3.由于建堆的时间比较多,因此堆排序并不太适合排序元素量比较少的情况

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: