1 算法描述

堆是一个完全二叉树,堆的存储可以使用数组(正是因为堆是一个完全二叉树才可以这么存储),堆分为大根堆和小根堆。

大根堆的定义:该完全二叉树的父节点都比子节点大。

小根堆的定义:该完全二叉树的父节点都比子节点小。

堆排序的思想是先构建一个大根堆(对父节点进行),然后开始排序过程。

堆排序过程:

  • 1 建堆:对父节点依次进行下滤操作,得到大根堆。
  • 2 排序:
    • 2.1 vector压入大根堆的末尾叶子节点
    • 2.2 将大根堆的末尾叶节点与根节点交换,执行下滤操作
    • 2.3 重复2.2的操作N次,直到数组有序

2 算法模版

堆排序的模版分为两个部分:

  • 1 建立大根堆
  • 2 排序

下滤操作:

void heapify(vector &array, int n, int i) {
	int largest = i;
	int lson = 2 * i + 1;
	int rson = 2 * i + 2;
	if (lson < n && array[largest] < array[lson])
		largest = lson;
	if (rson < n && array[largest] < array[rson])
		largest = rson;
	if (largest != i) {
		swap(array[largest], array[i]);
		heapify(array, n, largest);
	}
}

建立大根堆和排序:

void heapSort(vector &array, int n) {
	// 1 建堆
	for (int i = n / 2 - 1; i >= 0; i--) {
		heapify(array, n, i);
	}
	// 2 排序
	for (int i = n - 1; i > 0; i--) {
		swap(array[i], array[0]);
		heapify(array, i, 0);
	}

}

3 整体算法

 

// 1 堆一定是一个完全二叉树
// 2 堆序性 = 大根堆(大小小) + 小根堆(小大大)
// 3 堆的存储: 层数遍历的编号作为数组的索引
// 4 堆的操作: 下滤:将root节点与最大的子节点比较,小于则交换,直到叶节点为止,上滤相反
// 5 堆的建立: 自顶向下(上滤)
// 6 堆的应用: 优先队列,堆排序(将优先队列的最小值依次弹出即可)


void heapify(vector &array, int n, int i) {
	int largest = i;
	int lson = 2 * i + 1;
	int rson = 2 * i + 2;
	if (lson < n && array[largest] < array[lson])
		largest = lson;
	if (rson < n && array[largest] < array[rson])
		largest = rson;
	if (largest != i) {
		swap(array[largest], array[i]);
		heapify(array, n, largest);
	}
}


void heapSort(vector &array, int n) {
	// 1 建堆
	for (int i = n / 2 - 1; i >= 0; i--) {
		heapify(array, n, i);
	}
	// 2 排序
	for (int i = n - 1; i > 0; i--) {
		swap(array[i], array[0]);
		heapify(array, i, 0);
	}

}



int main() {
	vector array = {12, 98, 34, 24, 53, 0, 100, 5, 65, 99};
	for (auto a : array) {
		cout << a << endl;
	}
	cout << "start quickSort" << endl;
	heapSort(array, array.size());
	for (auto a : array) {
		cout << a << endl;
	}
	return 0;
}