看这篇前请先把我上一篇了解一下:深入理解数据结构第一弹——二叉树(1)——堆-CSDN博客

前言:

目录

一、堆排序

1、堆排序的大体思路

2、堆排序的实例讲解

二、堆排序的时间复杂度

向下排序的时间复杂度

向上排序的时间复杂度

堆排序整体的时间复杂度

总结


一、堆排序

1、堆排序的大体思路

在上一篇我们已经讲过了堆是什么东西,我们已经知道堆有大堆和小堆两种形式,堆排序的想法正是借助它的这个特点诞生的,例如:

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度-LMLPHP

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度-LMLPHP

2、堆排序的实例讲解

堆排序与堆相比并没有什么新东西,把我前面那章看明白,这里直接把代码呈上

(除了test.c)其他的是直接从上一章搬过来的

Seqlist.h

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int sz;
	int capacity;
}HP;
 
//初始化
void HeapInit(HP* php);
//销毁
void HeapDestory(HP* php);
//插入
void HeapPush(HP* php, HPDataType x);
//删除
void HeapPop(HP* php);
//找堆顶元素
HPDataType HeapTop(HP* php);
//判断是否为空
bool HeapEmpty(HP* php);
//算个数
int HeapSize(HP* php);

test.c

//堆排序
void HeapSort(int* a, int n)
{
	//建堆——向下调整建堆O(N-log(n))
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);

		//再调整,选出次小数
		AdjustDown(a, end, 0);
		end--;
	}
}
int main()
{
	int a[] = { 7,8,3,5,1,9,5,4 };
	HeapSort(a, sizeof(a) / sizeof(int));
	return 0;
}

Seqlist.c

//堆
//初始化
void HeapInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->capacity = 0;
	php->sz = 0;
}
//销毁
void HeapDestory(HP* php)
{
	free(php->a);
	free(php);
}
//交换
void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//删除
 
//向上调整(小堆)
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;
		}
	}
}
//向下调整
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child<n)
	{
		if (child+1<n&&a[child + 1] < a[child])
		{
			++child;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
 
//插入
void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->sz == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->sz] = x;
	php->sz++;
 
	//向上调整
	AdjustUp(php->a, php->sz - 1);
}
//删除
void HeapPop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));
	Swap(&php->a[0], &php->a[php->sz - 1]);
	php->sz--;
	//向下调整
	AdjustDown(php->a, php->sz,0);
}
//判断是否为空
bool HeapEmpty(HP* php)
{
	assert(php);
	return php->sz == 0;
}
//找堆顶元素
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));
	return php->a[0];
}
//算个数
int HeapSize(HP* php)
{
	assert(php);
	return php->sz;
}

实现上述代码,我们就可以实现堆排序了

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度-LMLPHP

二、堆排序的时间复杂度

向下排序的时间复杂度

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度-LMLPHP

向上排序的时间复杂度

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度-LMLPHP

堆排序整体的时间复杂度

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度-LMLPHP

计算堆排序整体的时间复杂度就是计算上面这两步的时间复杂度

第一步:

第二步:

因此,堆排序的时间复杂度为O(N+N*log(N))

总结

堆排序及其时间复杂度的讲解就到此为止了,如果有不理解的地方欢迎在评论区中指出或者与我私信交流,欢迎各位大佬来访!!!

创作不易,还请各位大佬点赞支持!!!

04-03 02:29