小堆:任意结点的关键码均小于它的左右孩子的关键码,位于堆顶的关键码最小,从根结点到每个结点的路径上的数组元素组成            的序列都是递增的。

大堆:任意结点的关键码均大于它的左右孩子的关键码,位于堆顶的关键码最大,从根结点到每个结点的路径上的数组元素组成            的序列都是递减的。

有上面的图可以看出:对存储在下标为0开始的数组中,因此在堆中给定下标i的结点:

1.如果i =0,结点i 是根结点,没有双亲结点; 否则结点i 的双亲结点为结点(i -1)/ 2;

2.如果2 * i + 1 <= n -1, 则结点i 的 孩子结点为2 * i +1,否则没有左孩子。

3.如果2 * i + 1 <= n -1, 则结点i 的 孩子结点为2 * i +2,否则没有右孩子。

堆在逻辑上:完全二叉树        物理上:有序线性表

向下调整的条件(堆的创建,删除):1.当前要调整的是叶子结点

                                                              2.当前要调整的已经满足对的性质了。

向上调整:用于堆的插入

堆创建的前提:1.左右子树都是堆

                          2. 对所有的叶子结点建堆

                          3.最后一个非叶子结点就是最后一个结点的双亲

                          4.最后一个结点的下标是size -1;

                         5.最后一个非叶子结点的下标是(size -1 -1)/ 2;

总结小点:找最大的几个值--->建小堆

                   找最小的几个值--->建大堆

                    升序---------------->建大堆

                    降序---------------->建小堆

Heap.h

#pragma once

#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<Windows.h>

typedef struct Heap{
	int array[100];
	int size;
}Heap;

void HeapInit(Heap *pH, int array[], int size)
{
	assert(pH);
	memcpy(pH->array, array, sizeof(int)* size);
	pH->size = size;
}
//交换函数
void Swap(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}
//向下调整   递归
void AdjustDownRecursion(Heap *pH, int parent)
{
	//判断是否是叶子节点
	//没有左子树,没有右子树
	//完全二叉树,没有左子树,就一定没有右子树
    //判断有没有左子树,是判断左子树的下标是否越界
	int left = 2 * parent + 1;
	int right = 2 * parent + 2;
	int maxChild;
	if (left >= pH->size){
		return;
	}
	maxChild = left;
	if (right < pH -> size&&pH->array[right]>pH->array[left]){
		maxChild = right;
	}
	if (pH->array[parent] > pH->array[maxChild]){
		return;
	}
	Swap(pH->array + parent, &(pH->array[maxChild]));
	AdjustDownRecursion(pH, maxChild);
}
//向下调整  非递归
void AdjustDownLoop(Heap *pH, int parent)
{
	while (1){	//判断是否是叶子节点
		//没有左子树,没有右子树
		//完全二叉树,没有左子树,就一定没有右子树
		//判断有没有左子树,是判断左子树的下标是否越界
		int left = 2 * parent + 1;
		int right = 2 * parent + 2;
		int maxChild;
		if (left >= pH->size){
			return;
		}
		maxChild = left;
		if (right < pH->size&&pH->array[right]>pH->array[left]){
			maxChild = right;
		}
		if (pH->array[parent] > pH->array[maxChild]){
			return;
		}
		Swap(pH->array + parent, &(pH->array[maxChild]));
		parent = maxChild;
	}
}

//建堆
void HeapMake(Heap*pH)
{
	int i;
	for (i = (pH->size - 2/ 2); i >= 0; i--){
		AdjustDownLoop(pH, i);
	}
}

int HeapTop(Heap*pH)
{
	return pH->array[0];
}

//求堆的大小
//int HeapSize(Heap*pH)
//{
//	return pH->size;
//}

//判断堆是否为空
int HeapIsEmpty(Heap*pH)
{
	return pH->size == 0 ? 1 : 0;
}

void HeapPop(Heap*pH)
{
	assert(pH);
	assert(pH->size > 0);
	pH->array[0] = pH->array[pH->size - 1];
	pH->size--;
	AdjustDownLoop(pH, 0);
}

void AdjustUp(Heap*pH, int child)
{
	int parent;
	while (1){
		parent = (child - 1) / 2;
		if (child == 0){
			//走到整棵树的根了
			break;
		}
		if (pH->array[parent] >= pH->array[child]){
			//满足堆的条件了
			break;
		}
		Swap(pH->array + parent, pH->array + child);
		child = parent;
	}
}
//建大堆
void AdjustDownArray(int array[], int size, int root)
{
	int parent = root;
	int left, right, max;
	while (1){
		left = parent * 2 + 1;
		right = parent * 2 + 2;
		if (left >= size){
			return;
		}
		max = left;
		if (right<size&&array[right]>array[left]){
			max = right;
		}
		if (array[parent] > array[max]){
			return;
		}
		Swap(array + parent, array + max);
		parent = max;
	}
}
//TopK问题
//在array中找到最小的K个数(建大堆)
int *TopK(int array[], int size, int k)
{
	int i;
	int *rarray = (int *)malloc(sizeof(int)*k);
	for (i = 0; i < k; i++){
		rarray[i] = array[i];
	}
	//建堆
	for (i = (k - 2) / 2; i >= 0; i--){
		AdjustDownArray(rarray, k, i);
	}
	for (i = k; i < size; i++){
		if (array[i] < rarray[0]){
			rarray[0] = array[i];
			//对rarray进行向下调整
			AdjustDownArray(rarray, k, 0);
		}
	}
	return rarray;
}
//堆排序 (从小到大  建大堆)
void HeapSortRight(int array[], int size)
{
	int i;
	for (i = size / 2 - 1; i >= 0; i--){
		AdjustDownArray(array, size, i);
	}
	for (i = 0; i < size;){
		Swap(&(array[0]), &(array[size - 1 - i]));
		AdjustDownArray(array, size - 1 - i, 0);
	}
}

void Test()
{
	Heap heap;
	int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
	int size = sizeof(array) / sizeof(int);

	HeapInit(&heap, array, size);
	HeapMake(&heap);
	for (int i = 0; i < heap.size; i++){
		printf("%d ", heap.array[i]);
	}
	printf("\n ");

	printf("Heap\n");
}

main.c

#include"Heap.h"

int main()
{
	Test();
	system("pause");
	return;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值