七大排序算法之堆排序

前言

堆排序也是一种非常重要的排序算法,但是在写堆排序算法之前,需要对堆的概念有一定了解,简单来说就是利用了大根堆和小根堆的特性,在大根堆中,堆顶的元素是整个堆元素中最大的,小根堆中,堆顶的元素是整个堆元素中最小的。

原理

其实原理简单点说,就是利用大根堆小根堆的性质,那么怎么根据大根堆小根堆的性质来实现排序的效果呢?

第一步,建堆,如果为升序,建大根堆,为降序,建小根堆。怎么将一个有序数组构建成一个堆呢?首先根据堆的特点,我们可以从堆的长度中心位置,也就是list.length/2的位置处,开始构建,然后获取当前节点、当前节点的左节点、当前节点的右节点中的最大值,并将最大值置于父节点的位置,循环遍历节点,直到为0的位置,也就是遍历到了堆顶的位置,至此,堆建立完毕。

时间复杂度

固定:为n*logn

代码

public class HeapSort {

	// 堆排序,利用大根堆/小根堆,堆顶元素最大/最小的特点,不断和堆底元素进行交换,从而排序
	
	// 时间复杂度固定为 n*Logn
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = new int[] { 8, 5, 0, 7, 3, 1, 2 };
		System.out.println("排序前");
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();

		heapSort(arr);

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

	
	public static void HeapAdjust(int[] array, int parent, int length) {
		int child = 2 * parent + 1; // 先获得左孩子
		while (child < length) {
			// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
			if (child + 1 < length && array[child] < array[child + 1]) {
				child++;
			}
			// 如果父结点的值已经大于孩子结点的值,则直接结束
			if (array[parent] >= array[child])
				// 跳出while循环体
				break;
			// 交换孩子节点和父节点的值
			int t;
			t = array[child];
			array[child] = array[parent];
			array[parent] = t;
			// 选取孩子结点的左孩子结点,继续筛选下一个节点
			parent = child;
			child = 2 * child + 1;
		}

	}

	public static void heapSort(int[] list) {
		// 循环建立初始堆
		for (int i = list.length / 2; i >= 0; i--) {
			HeapAdjust(list, i, list.length - 1);
		}
		// 进行n-1次循环,完成排序
		for (int i = list.length - 1; i > 0; i--) {
			// 最后一个元素和第一元素进行交换
			int temp = list[i];
			list[i] = list[0];
			list[0] = temp;
			// 筛选 R[0] 结点,得到i-1个结点的堆
			HeapAdjust(list, 0, i);
		}
	}

}

下一篇:归并排序

入口在此:点我学习归并排序

猜你喜欢

转载自blog.csdn.net/hq942845204/article/details/80157108