浅谈堆排序

堆排序:

堆是一颗完全二叉树,如果父节点的值都大于子节点,就称之为大根堆,如果父节点的值都小于子节点,就称之为小根堆。一般使用数组来存储这个二叉树结构。 

第i节点的左右孩子节点分别为2 ∗ i + 1和2 ∗ i + 2,它的父节点为(i - 1) / 2。由于是完全二叉树,假设节点的个数为size,则最后一个非叶子节点的编号为size / 2 - 1

堆排序时,先建大根堆,显然队是无序的,将堆顶元素和最后一个元素交换,最后一个元素显然是最大的,去掉该元素,对剩余元素进行上述操作直到剩余最后一个元素。

public static void heapAdjust(int[] numbers, int i, int size) { // 堆调整
    	int leftChild = 2 * i + 1; // i的左孩子节点序号
    	int rightChild = 2 * i + 2; // i的右孩子节点序号
    	int max = i;
    	if (i < size / 2) { // 如果i不是叶子节点,就不用进行调整
    		if (leftChild < size && numbers[leftChild] > numbers[max])
    			max = leftChild;
    		if (rightChild < size && numbers[rightChild] > numbers[max])
    			max = rightChild;
    		if (max != i) { // i不是最大,则需要调整以max为父节点的子树,使其成为大根堆
    			swap(numbers, i, max); // 交换i和max,使得以max为父节点的子树成为大根堆
    			heapAdjust(numbers, max, size); // 交换之后,以max为父节点的子树可能不是大根堆,需要继续调整以max为父节点的子树
    		}
    	}
}  
public static void buildMaxHeap(int[] numbers, int size) { // 建立大堆
	for (int i = size / 2 - 1; i >= 0; i--) // 非叶子节点最大序号值为size / 2 - 1
		heapAdjust(numbers, i, size);
}  
public static void swap(int[] numbers, int i, int j) { // 交换数组两个节点的值
  	int temp = numbers[i];  
  	numbers[i] = numbers[j];
  	numbers[j] = temp;  
}  
public static void heapSort(int[] numbers, int size) {
	buildMaxHeap(numbers, size);
	for (int i = size - 1; i >= 0; i--) {
        	swap(numbers, 0, i); // 交换堆顶元素和最后一个元素,实现将剩余元素中的最大者放到最后面
        	heapAdjust(numbers, 0, i); // 调整之后以堆顶节点为父节点的子树可能不是大根堆,需要继续调整以堆顶节点为父节点的子树
    	}
}

最好时间复杂度:O(nlogn)

最坏时间复杂度:O(nlogn)

平均时间复杂度:O(nlogn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值