数据结构之堆

堆分为最大堆和最小堆。
最大堆的特点:
1.每个节点最多可以有两个节点。
2.根节点的键值是所有堆节点中的最大值,且每个节点的值都比其孩子节点的值大。
3.除了根节点没有兄弟节点,最后一个左子节点可以没有兄弟节点,其他节点必须有兄弟节点。
最小堆特点与最大堆一样,只是第2点的最大变为最小。

堆是最有个性的树,它是用数组表示的树。
i的左子节点: 2i+1
i的右子节点: 2
i+2
i的父节点: (i-1) / 2

如下图,是一个最大堆:
在这里插入图片描述

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

#define DEFAULT_CAPACITY 128

typedef struct _Heap
{
	int* arr;		//存储元素的数组
	int size;		//当前已存储元素的个数
	int capacity;	//当前存储的容量
}Heap;

//初始化最大堆
bool initHeap(Heap& hp, int* original, int size);
static void buildHeap(Heap& hp);
static void adjustDown(Heap& hp, int index);
//插入元素
bool insertHeap(Heap& hp, int value);
static void adjustUp(Heap& hp, int index);
//堆元素出列
bool popMax(Heap& heap, int& value);



bool initHeap(Heap& hp, int* original, int size)
{
	int capacity = DEFAULT_CAPACITY > size ? DEFAULT_CAPACITY : size;
	hp.arr = new int[capacity];
	if (!hp.arr) return false;
	hp.capacity = capacity;
	hp.size = 0;
	if (size > 0)
	{
		//方式1
		memcpy(hp.arr, original, sizeof(int)*size);
		hp.size = size;
		buildHeap(hp);

		//方式2
// 		for (int i=0; i<size; i++)
// 		{
// 			insertHeap(hp, original[i]);
// 		}
	}
	return true;
}

void buildHeap(Heap& hp)
{
	for (int i = (hp.size - 1)/2; i >= 0; i--)
	{
		adjustDown(hp, i);
	}
}

void adjustDown(Heap& hp, int index)
{
	int cur = hp.arr[index];
	int parent, child;
	for (parent = index; (parent*2+1) < hp.size; parent = child)
	{
		child = parent * 2 + 1;
		if (child+1<hp.size && hp.arr[child+1] > hp.arr[child])
		{
			child++;
		}
		if (cur >= hp.arr[child])
		{
			break;
		}
		else 
		{
			hp.arr[parent] = hp.arr[child];
			hp.arr[child] = cur;
		}
	}
}

bool insertHeap(Heap& hp, int value)
{
	if (hp.size == hp.capacity) return false;
	int index = hp.size;
	hp.arr[hp.size++] = value;
	adjustUp(hp, index);
	return true;
}

void adjustUp(Heap& hp, int index)
{
	int cur = hp.arr[index];
	int child = index, parent = (child - 1) / 2;
	while (parent >= 0)
	{
		
		if (hp.arr[parent] < cur)
		{
			hp.arr[child] = hp.arr[parent];
			hp.arr[parent] = cur;
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

//删除最大的节点
bool popMax(Heap& hp, int& value)
{
	if (hp.size < 1) return false;
	value = hp.arr[0];
	hp.arr[0] = hp.arr[--hp.size];
	adjustDown(hp, 0);//向下执行堆调整
	return true;
}

int main()
{
	Heap hp;
	int value = -1;
	int origrinal[6] = { 1,3,5,22,35,35 };

	initHeap(hp, origrinal, 6);
	for (int i = 0; i < hp.size; i++)
	{
		printf_s("%d,",hp.arr[i]);
		
	}
	printf("\n");

	insertHeap(hp, 99);
	for (int i = 0; i < hp.size; i++)
	{
		printf_s("%d,", hp.arr[i]);
	}
	printf("\n");

	//堆中元素出列,从大到小依次出列
	while (popMax(hp, value))
	{
		printf("出列最大元素value:%d\n", value);
	}

	system("pause");
	return 0;
}

输出:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值