堆排序

堆排序
1.基本概念

堆: 堆是一棵完全二叉树,这是他的结构性
最大堆: 每个节点的值都大于或等于其左右孩子节点的值,这是他的堆序性
最小堆: 每个节点的值都小于或等于其左右孩子节点的值,这是他的堆序性

2.基本思想

堆排序就是把需要排序的序列构建最大堆或者最小堆,此时,最大值或者最小值就在堆顶位置,然后把该元素放于最后,对剩下的序列再一次构造堆,知道完成排序

堆排序的时间复杂度为 O(nlogn),由于要构造堆,因此不适用于序列个数较少的情况。

堆排序是一种不稳定的排序

3. 实现方式:

1.辅助数组:
构建堆完成后将最大或最小元素放于一个辅助数组,再重新构造堆

2.无需辅助数组:
构建堆完成后将最大或最小元素放于堆末端
再重新构造堆
在这里插入图片描述

public class SelectSort {

	/**
	 * 获取左孩子的下标
	 * 
	 * 父亲:(i-1)/2
	 * 左孩子:2*i+1
	 * 右孩子:2*i+2
	 * 
	 * @param i
	 * @return
	 */
	private static int leftChild(int i) {
		return (2 * i) + 1;
	}
	

	/**
	 * 交换
	 * @param a
	 * @param fromIndex
	 * @param toIndex
	 */
	private static void swapReference(int[] a,int fromIndex,int toIndex) {
		
		int tmp = a[fromIndex];
		a[fromIndex] = a[toIndex];
		a[toIndex] = tmp;
	}
	
	/**
	 * 重建堆(下滤)
	 * @param a
	 * @param i
	 * @param n
	 */
	private static void percDown(int[] a,int i,int n) {
		
		int child;
		//保存父节点值
		int tmp;
		//父节点和左右孩子比较,找出三者最大值做父节点建最大堆
		for(tmp = a[i];leftChild(i)<n;i = child) {
			child = leftChild(i);
			//左孩子<右孩子 ,child指向右孩子
			if(child != n-1 && a[child]<a[child+1]) {
				child++;
			}
			//孩子比父节点大,则交换
			if (tmp<a[child]) {
				a[i] = a[child];
			}
			//父节点最大则跳出循环
			else {
				break;
			}
		}
		//完成交换
		a[i] = tmp;
	}
	
	/**
	 * 堆排序
	 * 
	 * 1.建堆
	 * 2.删除最大节点(交换到数组(堆)末端)
	 * 3.重建堆
	 * 
	 * @param a
	 */
	public static void heapSort(int[] a) {
		
		for(int i = a.length/2-1;i>=0;i--) {
			percDown(a, i, a.length);
		}
		for(int i = a.length-1;i>0;i--) {
			swapReference(a,0,i);
			percDown(a, 0, i);
		}		
	}
	
	public static void main(String[] args) {
		int[] a = {1,8,2,6,4,2,3,8,4,6,10,12,45,21,31};
		System.out.println(a.length);
		heapSort(a);
		for(int i = 0;i<a.length;i++) {
			System.out.print(a[i]+"\t");
		}
	}
	
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值