[Структура данных — Алгоритм ручной сортировки, часть 4] Сортировка кучей, одна статья поможет вам понять сортировку кучей

Оглавление

1. Применение кучи — сортировка кучи

1.1 Анализ идеи кучной сортировки

2. Создайте кучу

2.1 Увеличение размера кучи: O(N*logN)

2.1.1 Изменить код вверх

2.1.2 Корректировка строительных норм отвала вверх

2.2 Регулировка кучи вниз: O(N)

2.2.1 Уменьшить код

2.2.2 Уменьшить код построения кучи

3. Код реализации сортировки кучи

4. Тест сортировки кучи


1. Применение кучи — сортировка кучи

Куча — это полное двоичное дерево, а полное двоичное дерево использует массивы для оптимального хранения данных.

Сортировка кучи заключается в использовании идеи кучи для сортировки.Она делится на два этапа:
1. Построить кучу

В порядке возрастания: построить большую кучу

По убыванию: построить небольшую кучу

2. Используйте идею удаления кучи для сортировки

Нисходящая корректировка используется как при построении кучи, так и при удалении кучи, поэтому сортировку кучи можно выполнить, освоив нисходящую корректировку.

1.1 Анализ идеи кучной сортировки

В этой статье мы используем небольшую кучу для объяснения, и сортировка маленькой кучи выполняется в порядке убывания.

Студенты, которые мало что знают о куче, могут взглянуть на статью о куче: нажмите здесь, чтобы перейти

1. Сначала мы смещаем элементы в массиве вниз, чтобы построить небольшую кучу;

2. Верхний элемент кучи должен быть наименьшим в массиве, поэтому мы меняем верхний элемент (первый элемент массива) на последний элемент массива, а отсутствующий элемент рассматриваем в конце массива как элемент в массиве (размер-- ) , затем начните с вершины кучи, чтобы настроить и перестроить маленькую кучу, и повторите это, чтобы добиться сортировки по убыванию (порядок по возрастанию может быть достигнут путем изменения маленькой кучи на большую кучу ).

2. Создайте кучу

Мы можем использовать корректировку вверх для создания куч или использовать корректировку вниз для построения куч.

Затем я должен выбрать того, у кого наименьшая временная сложность.Далее давайте проанализируем временную сложность двух куч:

2.1 Увеличение размера кучи: O(N*logN)

2.1.1 Изменить код вверх

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])//这里控制大小堆
		{
			Swap(&a[child], &a[parent]);

			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

2.1.2 Корректировка строительных норм отвала вверх

//建堆 -- 向上调整,时间复杂度:O(N*log(N))
for (int i = 0; i < size; i++)
{
	AdjustUp(a, i);
}

Давайте нарисуем картинку для анализа временной сложности построения кучи восходящей корректировки:

Куча представляет собой полное двоичное дерево, а полное двоичное дерево также является полным двоичным деревом.Поэтому мы берем полное двоичное дерево в качестве примера, чтобы сделать вывод, что временная сложность корректировки вверх и построения кучи составляет O(N*logN ).

2.2 Регулировка кучи вниз: O(N)

2.2.1 Уменьшить код

void AdjustDown(HPDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)//当child大于了数组大小就跳出循环
	{
		//找出左右孩子中小/大的那个(假设法)
		if (child + 1 < size && a[child + 1] < a[child])
		{
			child++;
		}

		if (a[child] < a[parent])
		{
			Swap(&a[parent], &a[child]);

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

2.2.2 Уменьшить код построения кучи

for (int i = (size - 1 - 1) / 2; i >= 0; i--)
{
    AdjustDown(a, size, i);
}

Давайте нарисуем картинку, чтобы проанализировать временную сложность построения кучи нисходящей корректировки:

Сложность времени корректировки в сторону уменьшения при создании кучи: O(N).

После такого анализа мы можем понять, что лучший выбор — скорректировать положительный стек вниз.

3. Код реализации сортировки кучи

//堆排序时间复杂度O(N + N*logN)
void HeapSort(int* a, int size)
{
	//升序 -- 建大堆
	//降序 -- 建小堆

	//建堆 -- 向上调整,时间复杂度:O(N*log(N))
	//for (int i = 0; i < size; i++)
	//{
	//	AdjustUp(a, i);
	//}

	//建堆 -- 向下调整,时间复杂度:O(N)
	//倒着调整
	//叶子节点不需要处理
	//倒数第一个非叶子节点:最后一个节点的父亲开始调整
	for (int i = (size - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, size, i);
	}

	//O(N*log(N))
	int end = size - 1;
	while (end)
	{
		//1.先交换
		Swap(&a[0], &a[end]);
		//2.再调整,选出当前大小的数组中最小数
		AdjustDown(a, end, 0);

		end--;
	}
}

4. Тест сортировки кучи

Мы построили небольшую кучу, поэтому последняя строка находится в порядке убывания.

*** Конец статьи ***

рекомендация

отblog.csdn.net/Ljy_cx_21_4_3/article/details/131065900