堆排序是利用“堆”的概念,将一列数进行排序。本文首先介绍“堆”的定义,说明“堆”排序的过程和解决思路,最后利用C++和Python实现算法。
堆的定义
具有n个元素的序列( k1,k2,...,kn ),当且仅当满足:
{ki≤k2iki≤k2i+1 (小顶堆) 或 {ki≥k2iki≥k2i+1 (大顶堆)
时,称之为“堆”。由堆的定义可看出,堆顶元素为最小值或最大值。堆排序过程
首先将一维数组存储的二叉树序列,通过调整其中元素的位置,使之成为一个“堆”,将其堆顶元素输出,然后调整剩下的 n−1 个元素使之成为一个堆,直到剩下两个元素,则交换他们的顺序,即可得有序序列。解决思路
(1)建立初始“堆”
a.对于有 n 个节点的二叉树,其最后一个节点是n/2 个节点的子树
b.从 n/2 个节点开始筛选,直到第一个节点结束。筛选过程如(2)所述。
(2)筛选过程
假设原先的 m 个数据已构成堆,输出堆顶元素后,还剩m−1 个元素。
a.将堆尾元素放入堆顶;
b.比较堆顶元素与其子节点,是否满足堆的条件,若不满足,则与其子节点中较大者交换;
c.向下判断左子节点,是否满足堆的条件,若不满足,则与其字节点中较大者交换;
d.判断右子节点,是否满足堆的条件,若不满足,则与其子节点中较大者交换。
e.重复a、b、c、d,直到判断结束,到达最后一个节点。C++实现
//打印排序结果函数
void Print(int a[],int n,int i=0)
{
//cout<<i<<endl;
cout<<"排序后的结果为:"<<endl;
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
//堆排序
void HeapAdjust(int a[],int s,int n) //s为需要调整的堆元素位置
{
int child=2*s+1; //左子节点位置
while (child<n)
{
if(child+1<n && a[child]<a[child+1])
{
child++;
}
if(a[s]<a[child])
{
int tem=a[s]; //储存,用于交换
a[s]=a[child];
a[child]=tem;
s=child;
child=2*s+1;
}else{break;}
}
}
void buildHeap(int a[],int n) //建立初始堆
{
for(int i=(n-1)/2;i>=0;i--) //最后一个节点所在父节点位置为(n-1)/2
{
HeapAdjust(a,i,n);
}
}
void HeapSort(int a[],int n)
{
buildHeap(a,n);
for(int i=n-1;i>0;i--)
{
int temp;
temp=a[i];a[i]=a[0];a[0]=temp;
HeapAdjust(a,0,i);
}
Print(a,n);
}
5.Python实现
'''输出排序结果函数'''
def Print(ddata):
n=len(ddata)
for i in range(n):
print ddata[i], #其中","为了不让其输出默认的换行符
'''堆排序'''
def heapAdjust(data,s,n): #堆调整函数,data---数据,s---为待调整节点位置,n---数据长度
child=2*s+1
while(child<n):
if(child+1<n and data[child]<data[child+1]):
child+=1
if(data[s]<data[child]):
data[s],data[child]=data[child],data[s]
s=child
child=2*s+1
else:
break
return data
def buildHeap(data,n): #建立初始堆
for i in range(-1,(n-1)/2)[::-1]: #[::-1]实现倒序循环
data=heapAdjust(data,i,n)
return data
def heapSort(data,n):
data=buildHeap(data,n)
for i in range(n-1)[::-1]:
data[0],data[i]=data[i],data[0]
data=heapAdjust(data,0,i)
Print(data)