1、堆(Heap)的种类及定义
常见的堆有两种,分别为大根堆和小根堆
小根堆的定义:
1、首先小根堆应该是一颗完全二叉树。
2、若根结点存在左孩子,则根结点的值小于等于左孩子结点的值。
3、若根结点存在右孩子,则根结点的值小于等于右孩子结点的值。
4.以左右孩子为根的子树有同样各是一个堆。
大根堆的定义与上述定义类似,把小于等于改为大于等于就行了。
2、堆的存储结构及堆排序
因为堆是一颗完全二叉树,所以采用顺序存储的方式比较适宜。
堆排序是一种有效的排序算法,可以借助大小根堆来实现。
1、用建堆算法建立原始堆。
2、堆尾元素与堆顶元素互换。
3、再次调用建堆算法建堆。
4、重复执行步骤2,直到所有元素排好序。
建立原始堆方法为:
先取i=[n/2](其中,i是第n个结点的双亲的编号),将以i结点为根的子树调整为堆;然后令i=i-1;在将以i结点为根的子树调整称为堆,直到i==1为止,初始堆建立完成。
假设,待排序的序列是:
16 14 10 8 7 9 3 2 4 3
堆排序算法:
/*将数组a[]进行调整使其成为小根堆*/
void Heapsift(Elemtype a[],int s, int m)
{
Elemtype temp;
int j;
temp=a[s],j=2*s; /*temp取a[s]的值*/
/*j取a[s]结点的左孩子的下标*/
while(j<=m)
{
if(j<m&&a[j]>a[j+1]); /*沿关键码较小的子结点向下筛选*/
j++; /*j为关键码较大的元素下标*/
if(temp>a[j])
{
a[s]=a[j];
s=j;
j=j*2;
}
else{
j=m+1; /*设置循环的终止*/
}
}
a[s]=temp; /*插入*/
}
/*对顺序表a进行堆排序*/
void HeapSort(ElemType a[],int length)
{
int i,j ;
ElemType temp;
for(i=length/2;i>=1;i--) /*将a[1]......a[length]建成初始堆*/
Heapsift(a,i,length);
for(j=length;j>=2;j--) /*进行n-1次循环,完成堆排序*/
{
temp=a[1]; /*堆顶与堆底元素交换*/
a[1]=a[j];
a[j]=temp;
HeapSift(a,1,1,j-1); /*将a[1]...a[i-1]重新调整为堆*/
}
}
注:堆排序是一种不稳定的算法!