1.堆
堆(Heap)是一种特殊的完全二叉树数据结构,具有以下两个主要特性:
- 结构特性: 
  
- 堆是一棵完全二叉树,即除了最后一层的叶子节点外,每一层都是满的,最后一层的叶子节点从左向右依次排列。
 
 - 堆序性: 
  
- 大堆(Max-Heap):对于每个节点,父节点的值大于或等于其子节点的值。大堆中,根节点的值是所有节点中最大的。
 - 小堆(Min-Heap):对于每个节点,父节点的值小于或等于其子节点的值。小堆中,根节点的值是所有节点中最小的。
 
 

2.堆的实现
2.1堆的定义
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	size_t size;
	size_t capacity;
}HP; 
2.2堆初始化
void HeapInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = php->capacity = 0;
} 
2.3堆的销毁
void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = php->capacity = 0;
} 
2.3打印
void HeapPrint(HP* php)
{
	assert(php);
	for (size_t i = 0; i < php->size; ++i)
	{
		printf("%d ", php->a[i]);
	}
	printf("\n");
} 
2.4向上调整堆的顺序(小堆)
void Swap(HPDataType* pa, HPDataType* pb)
{
	HPDataType tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
void AdjustUp(HPDataType* a, size_t child)
{
	size_t parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])     //小堆
		//if (a[child] > a[parent])   //大堆
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
 
2.5向堆中插入数据
void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		size_t newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = realloc(php->a, sizeof(HPDataType)* newCapacity);
		if (tmp == NULL)
		{
			printf("realloc failed\n");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newCapacity;
	}
	php->a[php->size] = x;
	++php->size;
	// 向上调整,控制保持是一个小堆
	AdjustUp(php->a, php->size - 1);
} 
2.6向下调整堆的顺序(小堆)
void AdjustDown(HPDataType* a, size_t size, size_t root)
{
	size_t parent = root;
	size_t child = parent * 2 + 1;
	while (child < size)
	{
		// 1、选出左右孩子中小的那个
		if (child + 1 < size && a[child+1] < a[child])
		{
			++child;
		}
		// 2、如果孩子小于父亲,则交换,并继续往下调整
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
} 
2.7删除堆顶的数据。
// 删除堆顶的数据。
void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	--php->size;
	AdjustDown(php->a, php->size, 0);
}
 
2.8判断堆是否为空
bool HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
} 
2.9查看堆的大小
size_t HeapSize(HP* php)
{
	assert(php);
	return php->size;
} 
2.10返回堆顶数据
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
} 
                


















