二叉堆的一些基本操作,以及升序降序

我要理解二叉树如何定义一个堆的

  • 必须是一颗完全二叉树
  • 我们可以分大堆和小堆
  • 这里主要通过顺序链表的方法定义堆

在这里插入图片描述

  • 这是一个从上往下的大堆

  • 我们要如何存储这个堆了,显然我们需要一个数组,然后通过写算法实现这个堆的顺序存储。

  • 这里主要说一下堆的升序与降序,以及初始化,插入删除吧。

  • 堆其实理解起来相比二叉树的链式存储要容易很多,堆升序时候我们其实主要需要的这是一个判断条件结点是否存在
    以及二叉树的一个基本关系式,parent = child * 2 + 1 || parent = child * 2 + 2

  • 好了还是看代码吧,短时间这个我也不知道怎么说了

#include <stddef.h>
#include <stdio.h>
#include <assert.h>

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

static void Swap(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}


void HeapInit(Heap *pH, int source[], int size)
{
	for (int i = 0; i < size; i++) {
		pH->array[i] = source[i];
	}
	pH->size = size;
}

void HeapAdjustDown(Heap *pH, int root)
{
	int parent = root;

	while (1) {
		// 先判断有没有孩子(叶子结点)
		// 数组角度去想	-> 孩子的下标是否越界
		// 只要判断左孩子的下标(因为是完全二叉树)
		int left = parent * 2 + 1;
		if (left >= pH->size) {
			// 越界,没有左孩子,也肯定没有右孩子
			return;
		}

		// 一定有左孩子
		int maxChild = left;
		if (2 * parent + 2 < pH->size && pH->array[2 * parent + 2] > pH->array[left]) {
			// 前一个条件是判断右孩子有没有
			// 后一个条件判读是右孩子是否比左孩子大
			maxChild = 2 * parent + 2;
		}

		if (pH->array[parent] > pH->array[maxChild]) {
			return;
		}

		// 交换 root 和 maxChild 下标所在的值
		int t = pH->array[parent];
		pH->array[parent] = pH->array[maxChild];
		pH->array[maxChild] = t;

		parent = maxChild;
	}
}

// 1. 数组的越界判断不对, 是否 == size
// 2. array[left] == NULL	array -> int[]	这么判断左孩子在不在是错的
// 3. 交换的时候,交换的下标,而不是下标所在的值
void HeapAdjustDown2(Heap *pH, size_t root)
{
	size_t parent = root;
	size_t left, right;
	size_t maxChild;

	left = 2 * root + 1;
	right = 2 * root + 2;
	while (left < (size_t)pH->size) {
		maxChild = left;
		if (right < (size_t)pH->size && pH->array[left] < pH->array[right]) {
			maxChild = right;
		}

		if (pH->array[maxChild] < pH->array[parent]) {
			break;
		}

		Swap(pH->array + maxChild, pH->array + parent);
		parent = maxChild;
		left = 2 * parent + 1;
		right = 2 * parent + 2;
	}
	// left 不存在
}

// i-- 写成 i++
void HeapMakeHeap(Heap *pH)
{
	// [(size - 2) / 2, 0]
	// 理解循环的区间的来历
	for (int i = (pH->size - 2) / 2; i >= 0; i--) {
		HeapAdjustDown(pH, i);
	}
}

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

	HeapAdjustDown(pH, 0);
}

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

void HeapAdjustUp(Heap *pH, int child)
{
	int parent;
	while (child > 0) {
		parent = (child - 1) / 2;
		if (pH->array[parent] >= pH->array[child]) {
			return;
		}

		Swap(pH->array + parent, pH->array + child);

		child = parent;
	}
}

void HeapPush(Heap *pH, int data)
{
	assert(pH->size < 100);
	pH->array[pH->size++] = data;
	HeapAdjustUp(pH, pH->size - 1);
}

#include <stdio.h>

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

	Heap	heap;
	HeapInit(&heap, array, size);
	HeapMakeHeap(&heap);

	HeapPush(&heap, 100);
	printf("%d\n", HeapTop(&heap));

	printf("建堆完成\n");
}

int main()
{

	Test();


	return 0;
}

我们初始化放入的数据是 int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
我们看一下我们分别降序升序以后队中元素的变化吧

  • 降序以后

在这里插入图片描述

  • 我们插入100升序以后
    在这里插入图片描述
  • 好了,大概就这样了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值