堆的建立及增删查改等操作

Posted 银背欧尼酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆的建立及增删查改等操作相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

heap.c

#include <malloc.h>
#include <stdio.h>

void Swap(DataType* left, DataType* right)
{
	int temp = *left;
	*left = *right;
	*right = temp;
}

void AdjustDown(DataType array[], int size, int parent)
{
	//默认让parent标记左孩子,因为parent可能不存在右孩子
	int child = parent * 2 + 1;
	while (child < size)
	{
		//判断右孩子是否存在
		//有孩子存在的情况下找到左右孩子中比较小的
		if (child+1<size&&array[child + 1] < array[child])
			child += 1;
		//检测双亲是否满足堆的特性
		if (array[child] < array[parent])
		{
			Swap(&array[child], &array[parent]);
			//较大的双亲往下移动,可能会导致其子树不满足堆的特性
			//因此需要继续往下调整
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			return;
		}

	}

}

void AdjustUp(DataType array[], int size)
{
	int child = size - 1;
	int parent = (child - 1)/2;
	while (child)
	{
		if (array[child] < array[parent])
		{
			Swap(&array[child], &array[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			return;
		}
	}

}
//***********************************************
//建堆操作,巨重要!!
//整个程序的难点就在这里,这里理解了后面的就都可以理解

void HeapInit(Heap* hp, DataType* array, DataType size)
{
	int LastNotLeaf = 0;
	assert(hp);
	hp->array = (DataType*)malloc(sizeof(DataType) * size);
	if (NULL == hp->array)
	{
		assert(0);
		return ;
	}
	hp->capacity = size;
	for (int i = 0; i < size; ++i)
	{
		hp->array[i] = array[i];
	}
	hp->size=size;
	//1.找到最后一个非叶子节点
	LastNotLeaf = (size - 2)/2;
	//2.从该节点位置逐个往前直到根节点,遇到一个结点应用‘向下调整’
	for (int root = LastNotLeaf; root >= 0; root--)
	{
		AdjustDown(hp->array,hp->size,root);
	}
}

//***************************************************

void CheckCapacity(Heap* hp)
{
	assert(hp);
	if (hp->size == hp->capacity)
	{
		hp->array = (DataType*)realloc(hp->array, sizeof(DataType)*hp->size*2);
		if (NULL == hp->array)
		{
			assert(0);
			return;
		}
		hp->capacity *= 2;
	}
}

//插入
void HeapInsert(Heap* hp, DataType data)
{
	//1.先检测空间是否足够,如果不够进行扩容
	CheckCapacity(hp);
	//2.将元素插入到最后一个有效元素之后
	hp->array[hp->size++] = data;
	//3.插入的新元素可能破坏堆的特性,因此需要对堆进行调整
	//这里选择‘向上调整’
	AdjustUp(hp->array, hp->size);

}

//删除堆顶元素
//**************************************
//删除原理
//1.将堆顶元素与堆中最后一个元素交换
//2.将有效元素个数减去1
//3.将堆顶元素'往下调整'

void HeapErase(Heap* hp)
{
	if (HeapEmpty(hp))
		return;
	//1.将堆顶元素与堆中最后一个元素交换
	Swap(&hp->array[0], &hp->array[hp->size - 1]);
	//2.将有效元素个数减去1
	hp->size -= 1;
	//3.将堆顶元素往下调整
	AdjustDown(hp->array, hp->array, 0);

}
//获取堆顶元素
DataType HeapTop(Heap* hp)
{
	//assert(hp);因为HeapEmpty函数中进行了assert(hp)判断
	//所以此处不用再次判断
	assert(!HeapEmpty(hp));
	return hp->array[0];
}
DataType HeapEmpty(Heap* hp)
{
	assert(hp);
	return 0 == hp->size;
}
int HeapSize(Heap* hp)
{
	assert(hp);
	return hp->size;
}
void HeapDestory(Heap* hp)
{
	assert(hp);
	if (hp->array)
	{
		free(hp->array);
		hp->array = NULL;
		hp->capacity = 0;
		hp->size = 0;
	}
}

void TestHeap()
{
	int array[] = { 6,7,8,3,5,1 };
	Heap hp;
	
	HeapInit(&hp, array, sizeof(array) / sizeof(array[0]));

	printf("top=%d\\n", HeapTop(&hp));
	printf("size=%d\\n", HeapSize(&hp));

	HeapErase(&hp);
	printf("top=%d\\n", HeapTop(&hp));
	printf("size=%d\\n", HeapSize(&hp));

	HeapInsert(&hp, 9);
	printf("top=%d\\n", HeapTop(&hp));
	printf("size=%d\\n", HeapSize(&hp));

	HeapDestory(&hp);
}

heap.h


typedef int DataType;

typedef struct Heap
{
	DataType* array;
	DataType capacity;
	DataType size;
}Heap;

void HeapInit(Heap* hp, DataType* array,DataType size);
//插入
void HeapInsert(Heap* hp, DataType data);

//删除 
void HeapErase(Heap* hp);
//获取堆顶元素
DataType HeapTop(Heap* hp);
DataType HeapEmpty(Heap* hp);
int HeapSize(Heap* hp);
void HeapDestory(Heap* hp);

//
//测试
void TestHeap();

以上是关于堆的建立及增删查改等操作的主要内容,如果未能解决你的问题,请参考以下文章

单链表的增删查改等基本操作C++实现

数据结构之单链表的增删查改等操作画图详解

c++单链表构造函数运算符重载析构函数增删查改等

数据结构学习笔记(数据结构概念顺序表的增删查改等)详细整理

捋一捋Python的文件属性和增删查改等(下)

捋一捋Python的文件属性和增删查改等(下)