排序-堆排序

在堆排序中,把待排序的文件逻辑上看作是一棵顺序二叉树,
堆是一个具有这样性质的顺序二叉树,每个非终端结点(记录)的关键字大于等于它的孩子结点的关键字。
显然,在一个堆中,根结点具有最大值(指关键字,下同),而且堆中任何一个结点的非空左、右子树都是一个堆,它的根结点到任一叶子的每条路径上的结点都是递减有序的。

堆排序的基本思想是:首先把待排序的顺序表示(一维数组)的文件(R1,R2,…,Rn)在概念上看作一棵顺序二叉树,并将它转换成一个堆。这时,根结点具有最大值,删去根结点,然后将剩下的结点重新调整为一个堆。反复进行下去,直到只剩下一个结点为止。


堆排序的关键步骤是如何把一棵顺序二叉树调整为一个堆。初始状态时,结点是随机排列的,需要经过多次调整才能把它转换成一个堆,这个堆叫做初始堆。建成堆之后,交换根结点和堆的最后一个结点的位置,同时,剩下的结点(除原堆中的根结点)又构成一棵顺序二叉树。

这时,根结点的左、右子树显然仍都是一个堆,它们的根结点具有最大值(除上面删去的原堆中的根结点)。把这样一棵左、右子树均是堆的顺序二叉树调整为新堆,是很容易实现的。

堆排序中调整堆的伪代码如下:
 void adjust(struct node r[m+1],int m)
/* 将文件(r[1],r[2],…,r[m])解释为一棵顺序二叉树,将其中以r[i]为根结点的二叉树调整
为一个堆,设以r[i]为根的二叉树的左,右子树已是堆,1≤i≤1[m/2] */
{ x=r[i];j=2*i; /*求出r[i]的左孩子r[2*i],即r[j] */
while (j<=m) /*有左孩子*/
{ if ((j<m) &&(r[j].key<r[j+1].key)) /*比较左、右孩子*/
j=j+1; /*左孩子<右孩子*/
if (x.key<r[j].key) /*比较根结点和它的大孩子*/
{ r[i]=r[j]; /*大孩子上移到它的双亲位置*/
i=j; /*今 r[j]为根结点*/
j=2*i; /*求出左孩子*/
}
else j=m+1 /*根不小于它的任一孩子时,强迫退出while循环*/
}
r[i]:=x; /*将存放在x中的根结点放到r[i]中*/
}


========================
以下为Java代码实现的堆排序程序代码:

public class HeapSort2 {



public void HeapAdjust(int array[], int i, int nLength)

{
int nChild, nTemp;

//数组0为下标的话 2*i+1表示左子树根节点 2*i+2表示右子树根节点
for (nTemp = array[i]; 2 * i + 1 < nLength; i = nChild)
{

// 子结点的位置是 父结点位置 * 2 + 1

nChild = 2 * i + 1;
// 得到子结点中较大的结点
if (nChild != nLength - 1 && array[nChild + 1] > array[nChild])
++nChild;
// 如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
if (nTemp < array[nChild])

{
array[i] = array[nChild];
}

else // 否则退出循环

{
break;
}

}

// 最后把需要调整的元素值放到合适的位置
array[i] = nTemp;

}




// 堆排序算法
public void HeapSort(int array[], int length)

{
// 调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
for (int i = length / 2 - 1; i >= 0; --i)

{

HeapAdjust(array, i, length);

}



// 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素

int t=0;
for (int i = length - 1; i > 0; --i)

{

// 把第一个元素和当前的最后一个元素交换,

// 保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
t=array[0];
array[0]=array[i];
array[i]=t;
//Swap(&array[0], &array[i]);

// 不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值

HeapAdjust(array, 0, i);

}

}



public static void main(String[] args)
{
HeapSort2 hs=new HeapSort2();
int arr[]=new int[]{12,91,3,66,79,32,55};


hs.HeapSort(arr, arr.length);

for(int i=0;i<arr.length;i++)
{
System.out.println(arr[i]);
}

}


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值