堆排序的实现
(—)创建初始堆
(二)堆排序
在创建初始堆之前首先要了解一些关于堆的概念,还需要了解一些关于平衡二叉树的内容
(1)堆的节点数 =n/2; 并且是只舍不入;
(2)最后一个堆结点=(n/2)-1;
(3)对于任意结点a[x],可以找到它子结点上的内容a[2x+1]和a[2x+2]
于其子结点的值,有效的创建了一个堆
int i,j,j2,k;
int tmp;
//外循环 :考虑所有的结点,从最后一个开始,直到根部
for(k =(n>>1)-1;k>=0;k--)
{
//评价至该结点的k个点
// k子女上的j2+1 与j2+2 结点
tmp =data[k];
//内循环:对于每个变化的结点,循环检查引起变
化的子节点
for( j=k;(j<<1)<=n-2;j=i)
{
//查找节点k的最大子女
j2 = j<<1;
if(j2+2>n-1)//只有一个子女
i=j2+1;
else
{ //有两个子女
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
//此时,i指向具有最大值的子女
if(tmp<data[i])
data[j]= data[i];
else
break;
}
data[j]= tmp;
}
{
//至数组后部(已排序)的k个结点
//根部与后部的元素交换
tmp = data[k];
data[k] =data[0];
//再把数组压入堆中
for(j=0;(j<<1) <= k-2;j=i)
{
j2 =j<<1;
if( j2+2 > k-1 )
i=j2+1;
else
{
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
if(tmp<data[i])
data[j]=data[i];
else
break;
}
data[j]=tmp;
}
for(j=0;j<n;j++)
cout<<data[j];
}
下面是堆排序的完整实现的代码示例。
#include<iostream>
using namespace std;
void heapsort(int *data,int n )
{
int i,j,j2,k;
int tmp;
//外循环 :考虑所有的结点,从最后一个开始,直到根部
for(k =(n>>1)-1;k>=0;k--)
{
//评价至该结点的k个点
// k子女上的j2+1 与j2+2 结点
tmp =data[k];
//内循环:对于每个变化的结点,循环检查引起变
化的子节点
for( j=k;(j<<1)<=n-2;j=i)
{
//查找节点k的最大子女
j2 = j<<1;
if(j2+2>n-1)//只有一个子女
i=j2+1;
else
{ //有两个子女
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
//此时,i指向具有最大值的子女
if(tmp<data[i])
data[j]= data[i];
else
break;
}
data[j]= tmp;
}
for(k=n-1;k>0;k--)
{
//至数组后部(已排序)的k个结点
//根部与后部的元素交换
tmp = data[k];
data[k] =data[0];
//再把数组压入堆中
for(j=0;(j<<1) <= k-2;j=i)
{
j2 =j<<1;
if( j2+2 > k-1 )
i=j2+1;
else
{
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
if(tmp<data[i])
data[j]=data[i];
else
break;
}
data[j]=tmp;
}
for(j=0;j<n;j++)
cout<<data[j];
}
int main()
{
int data[10]={9,6,3,8,5,2,7,4,1,0};
heapsort(data,10);
return 0;
}
(三)
堆排序的优缺点
其复杂度为O(nlog2n),也适合较小量的数据
优点:
(1)平均情形和最坏情形时效率都很高。
(2)运行时占用内存较少
缺点:
(1)算法不稳定
(—)创建初始堆
(二)堆排序
在创建初始堆之前首先要了解一些关于堆的概念,还需要了解一些关于平衡二叉树的内容
(1)堆的节点数 =n/2; 并且是只舍不入;
(2)最后一个堆结点=(n/2)-1;
(3)对于任意结点a[x],可以找到它子结点上的内容a[2x+1]和a[2x+2]
(——)创建一个堆
实现原理:
它考察堆的各个结点并且使之成为一个堆。这意味着各个结点的值无论何时小于它的子结点的值,都要对此节点与最大的子节点进行交换。对于每个结点,要检查是否应该改变,并且递归检查引起变化的子节点。
于其子结点的值,有效的创建了一个堆
int i,j,j2,k;
int tmp;
//外循环 :考虑所有的结点,从最后一个开始,直到根部
for(k =(n>>1)-1;k>=0;k--)
{
//评价至该结点的k个点
// k子女上的j2+1 与j2+2 结点
tmp =data[k];
//内循环:对于每个变化的结点,循环检查引起变
化的子节点
for( j=k;(j<<1)<=n-2;j=i)
{
//查找节点k的最大子女
j2 = j<<1;
if(j2+2>n-1)//只有一个子女
i=j2+1;
else
{ //有两个子女
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
//此时,i指向具有最大值的子女
if(tmp<data[i])
data[j]= data[i];
else
break;
}
data[j]= tmp;
}
(二)堆排序
实现原理:
取堆的的根节点,也就是数组中最大的数,把它与数组中的最后一个元素交换。这个元素是最后一个结点最后一个树叶的子女。此时,前根元素恰好位于它应在的位置。但是要对新堆进行判断。方法同创建堆中的内循环相同。当新堆的重新判断完成后,再一次得到根元素,且把它与最后一个结点的最后一个页结点交换。
{
//至数组后部(已排序)的k个结点
//根部与后部的元素交换
tmp = data[k];
data[k] =data[0];
//再把数组压入堆中
for(j=0;(j<<1) <= k-2;j=i)
{
j2 =j<<1;
if( j2+2 > k-1 )
i=j2+1;
else
{
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
if(tmp<data[i])
data[j]=data[i];
else
break;
}
data[j]=tmp;
}
for(j=0;j<n;j++)
cout<<data[j];
}
下面是堆排序的完整实现的代码示例。
#include<iostream>
using namespace std;
void heapsort(int *data,int n )
{
int i,j,j2,k;
int tmp;
//外循环 :考虑所有的结点,从最后一个开始,直到根部
for(k =(n>>1)-1;k>=0;k--)
{
//评价至该结点的k个点
// k子女上的j2+1 与j2+2 结点
tmp =data[k];
//内循环:对于每个变化的结点,循环检查引起变
化的子节点
for( j=k;(j<<1)<=n-2;j=i)
{
//查找节点k的最大子女
j2 = j<<1;
if(j2+2>n-1)//只有一个子女
i=j2+1;
else
{ //有两个子女
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
//此时,i指向具有最大值的子女
if(tmp<data[i])
data[j]= data[i];
else
break;
}
data[j]= tmp;
}
for(k=n-1;k>0;k--)
{
//至数组后部(已排序)的k个结点
//根部与后部的元素交换
tmp = data[k];
data[k] =data[0];
//再把数组压入堆中
for(j=0;(j<<1) <= k-2;j=i)
{
j2 =j<<1;
if( j2+2 > k-1 )
i=j2+1;
else
{
if(data[j2+1]<data[j2+2])
i=j2+2;
else
i=j2+1;
}
if(tmp<data[i])
data[j]=data[i];
else
break;
}
data[j]=tmp;
}
for(j=0;j<n;j++)
cout<<data[j];
}
int main()
{
int data[10]={9,6,3,8,5,2,7,4,1,0};
heapsort(data,10);
return 0;
}
(三)
堆排序的优缺点
其复杂度为O(nlog2n),也适合较小量的数据
优点:
(1)平均情形和最坏情形时效率都很高。
(2)运行时占用内存较少
缺点:
(1)算法不稳定