其他分享
首页 > 其他分享> > 堆排序

堆排序

作者:互联网

堆排序

堆的概念

堆作为一种数据结构,其特征为:

堆的成形

堆的成形称为"heapify",对应函数实现为:

void heapify(int arr[], int n, int i) {
	if (i >= n) {
		return ;
	}
	int max = i;
	int left = 2 * i + 1, right = 2 * i + 2;
	if (left < n && arr[max] < arr[left]) {
		max = left;
	}
	if (right < n && arr[max] < arr[right]) {
		max = right;
	}
	if (max != i) {
		swap(arr, max, i);
		heapify(arr, n, max);
	}
}

从代码中可以看到,对某一个非叶节点,比较其与左、右子节点的大小,如果小于其子节点,则与值较大的子节点交换值。然后对交换了值的子节点进行递归调用。

如果有一颗已经是堆的二叉树某一个节点被替换,则直接对这个节点进行"heapify"操作可以使得其重新变成一个堆。

堆的构造

根据无序数组构造一个堆的过程称为堆的构造,其对应函数为:

void build_heap(int arr[], int n) {
	int last_node = n - 1;
	int parent = (last_node - 1) / 2;
	int i;
	for (i = parent; i >= 0; i--) {
		heapify(arr, n, i);
	}
}

其基本思想就是遍历每一个父节点并进行"heapify"操作,这是一个自底向顶的过程。对于倒数第二层的父节点来说,"heapify"可以直接构造一个完整的堆,当遍历到该父节点的父节点时,如果在进行"heapify"操作时与该父节点进行了交换的操作,则会递归调用heapify()再次对该父节点进行"heapify"操作使得重新成堆。这样遍历完成后整个二叉树就都是一个有序的堆了。

堆排序

对于一个已经成型的堆进行排序就非常简单了,只需要遍历堆中的所有节点,在每次遍历中都将根节点与当前遍历的最后一个节点进行交换,这样就把当前堆的最大值交换到了最后。然后在堆内将最后一个节点割去,重新进行"heapify"操作使得堆再次成型。

void heap_sort(int arr[], int n) {
	build_heap(arr, n);
	int i;
	for (i = n - 1; i >= 0; i--) {
		swap(arr, 0, i);
		heapify(arr, i, 0);
	}
}

标签:arr,遍历,int,max,堆排序,heapify,节点
来源: https://www.cnblogs.com/lunar-ubuntu/p/13843243.html