堆排序

7 篇文章 0 订阅

堆的概念

堆是具有下列性质的二叉树:每个结点的值都大于或等于其左右孩子结点的值,成为大顶堆,反之,则是小顶堆。

如果按照层序遍历的方式给结点从1开始编号,则结点满足一下关系:


这里i小于等于[n/2]是因为二叉树的性质5:一颗完全二叉树,如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲结点是[i/2]。那么对于n个节点的二叉树而言,它的i值自然就是小于等于[n/2]。这个结论在后面的代码中会运用到。

如果将上述大顶堆用层序遍历存入数组,则一定满足上面的关系,但需要注意的是数组下标是从0开始,对应i编号的关键字在数组中其实是i-1

0      1      2      3      4      5      6      7      8
90    70    80    60    10    40    50    30   20

堆排序算法

    堆排序就是利用堆(我用的是大顶堆)进行排序的方法。

    思想:构造大顶堆后,整个序列的最大值就是堆顶的根结点。移走根结点,然后将剩余的序列重新构造成大顶堆,如此反复,最终将会得到一个有序序列。移走根节点其实就是将其与堆数组的末尾元素交换。

代码

//排序算法中用的比较频繁 
	public static void swap(int[] test,int i,int j) {
		int temp = test[i];
		test[i] = test[j];
		test[j] = temp;
	}
public static void heapSort(int[] test) {
		//构造大顶堆 按照层序遍历的方式给节点编号
		//将每个非终端节点 (1~test.length/2对应编号的节点)当作根节点,将其和其子树调整成大顶堆
		for (int i = test.length / 2; i > 0; i--) {
			heapAdjust(test,i,test.length);
		}
		for (int i = test.length -1; i > 0; i--) {
			//将根节点也就是堆顶记录与末尾元素交换
			swap(test, 0, i);
			//交换过后,末尾元素就是最大值了
			//重构大顶堆
			heapAdjust(test, 1, i);
		}
	} 
//构造大顶堆 第一个参数是编号,第二个参数是指定数组的长度
	private static void heapAdjust(int[] test, int s, int m) {
		//注意:这里s和i都是编号,对应数组的计算的下标都要减1
		int temp = test[s-1];
		for (int i = 2 * s; i <= m; i*=2) {
			//找以s作为编号的节点下的孩子中的最大值
			//i < m说明不是最后一个元素,否则数组下标越界
			if (i < m && test[i-1] < test[i]) {//左孩子小于右孩子
				++i;//i为关键字较大的记录的下标
			}
			//根节点如果已经是最大了的,就跳出循环
			if (temp >= test[i-1]) {
				break;
			}
			test[s-1] = test[i-1];
			//将编号i的节点赋给s
			s = i;
		}
		//for循环结束后 插入
		test[s-1] = temp;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值