[C/C++]数据结构 堆排序(详细图解)

一:前言

        在[C/C++]数据结构 堆的详解中,介绍了什么是堆,并且完成了堆的实现和一系列接口,包括向上调整法和向下调整法等,接下来小编介绍一个有点量级的排序方法------堆排序,时间复杂度为O(n*lgn)

二:堆排序详解

2.1 方法介绍

1.首先将待排序数组建为大堆,此时堆顶元素就为数组最大值了

2.交换堆顶和堆尾元素,此时最大元素就到了堆尾,目前数组最大元素就排好了,现在就假设堆里没有当前这个最大元素了,堆头下面的左右子树仍然是大堆,只需要再将堆顶元素向下调整到合适位置,剩下的n-1个元素还是大堆

3.堆头堆尾交换,向下调整,如此反复就可排序

ps.排序以升序为例,升序建大堆,降序建小堆        


那么怎么将待排序数组建为大堆呢?

        假设数组第一个元素是堆,再把第二个元素插入,向上调整为堆,插入第三个元素时,前两个是堆,向上调整,插入第四个元素时,前三个元素是堆,以此反复就可以把所有元素建为堆

//建堆
	for (int i = 1; i < size; i++)
	{
		AdjustUp(a, i);
	}

2.2 排序

     假设我们的待排序数组为:

  建好大堆以后就可以开始排序了

过程如下:

处理最大元素:

先将堆头元素和堆尾元素交换

忽略9,将1向下调整到合适位置

处理次大元素:

再次堆头堆尾交换

忽略8和9,将1向下调整到合适位置

处理第三大元素:

堆头堆尾交换

忽略6和8和9,将2向下调整到合适位置

处理第N大元素:

........................

其实堆排序的实质就是选择排序,每次可以选出一个最大数,放在堆尾,再去处理前n-1个数

代码实现:

#include<stdio.h>
typedef int HeapDataType;

void swap(HeapDataType* a, HeapDataType* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//大堆
void AdjustUp(HeapDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[parent] < a[child])
		{
			swap(&a[parent], &a[child]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//大堆
void AdjustDown(HeapDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;

	while (child<size)
	{
		//找较大的孩子
		if (a[child + 1] > a[child] && child+1<size)
		{
			child = child + 1;
		}

		if (a[parent] < a[child])
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(HeapDataType* a, int size)
{
	//建堆
	for (int i = 1; i < size; i++)
	{
		AdjustUp(a, i);
	}
	//排序:升序
	int end = size - 1;
	while (end>0)
	{
		swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);  //end指最后一个元素,同时end的值为前面元素的个数
		end--;
	}
}
测试:
int main()
{
	int a[] = { 9,8,6,5,4,2,2,1 };
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

堆排序是一种基于堆数据结构的排序算法,其时间复杂度为O(nlogn)。下面是C语言实现堆排序的代码: ```c #include <stdio.h> // 交换两个元素 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } // 调整堆 void heapify(int arr[], int n, int i) { int largest = i; // 最大值 int left = 2 * i + 1; // 左子节点 int right = 2 * i + 2; // 右子节点 // 如果左子节点比当前节点大,则更新最大值 if (left < n && arr[left] > arr[largest]) largest = left; // 如果右子节点比当前节点大,则更新最大值 if (right < n && arr[right] > arr[largest]) largest = right; // 如果最大值不是当前节点,则交换元素并继续调整堆 if (largest != i) { swap(&arr[i], &arr[largest]); heapify(arr, n, largest); } } // 堆排序 void heapSort(int arr[], int n) { // 构建堆(从最后一个非叶子节点开始) for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); // 逐个提取元素并调整堆 for (int i = n - 1; i >= 0; i--) { swap(&arr[0], &arr[i]); // 将当前最大值移动到数组末尾 heapify(arr, i, 0); // 调整堆 } } // 测试代码 int main() { int arr[] = {12, 11, 13, 5, 6, 7}; int n = sizeof(arr) / sizeof(arr[0]); heapSort(arr, n); printf("排序后的数组:\n"); for (int i = 0; i < n; i++) printf("%d ", arr[i]); printf("\n"); return 0; } ``` 代码中,`heapify`函数用于调整堆,`heapSort`函数用于进行堆排序。首先构建堆,然后逐个提取元素并调整堆,最终得到有序数组。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张呱呱_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值