数据结构:堆的实现(C实现)

这篇具有很好参考价值的文章主要介绍了数据结构:堆的实现(C实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据结构:堆的实现(C实现),数据结构,数据结构,c语言,算法

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》


一、堆

当一颗完全二叉树用顺序表来存储时,其被称为堆。

  • 堆总是一棵完全二叉树
  • 堆的某个节点的值总是不大于(大堆)或不小于(小堆)其父节点的值

其可以被用来解决top k 问题 或 堆排序
数据结构:堆的实现(C实现),数据结构,数据结构,c语言,算法

下面就是要实现的堆的功能 重点在于堆的插入堆的删除


//堆的构建
void HeapInit(Heap* hp);

//堆的销毁
void HeapDestroy(Heap* hp);

//堆的插入
void HeapPush(Heap* hp, HPDataType x);

//堆的删除
void HeapPop(Heap* hp);

//取堆顶的数据
HPDataType HeapTop(Heap* hp);

//堆的数据个数
int HeapSize(Heap* hp);

//堆的判空
bool HeapEmpty(Heap* hp);

二、实现思路

下部分的图,都以逻辑结构为主!!!
这里构建的是小堆。

1. 结构的定义

堆就是用顺序表来存储一颗完全二叉树,那么堆的结构就与顺序表的结构相同。
一个指向动态开辟空间的指针(data),一个变量记录空间大小(capacity),一个变量记录空间中有效数据(size)。

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* data;
	int capacity;
	int size;
}Heap;

2. 堆的构建 (HeapInit)

malloc一块空间,用data记录其地址,capacity记录此时空间大小,size置0(此时空间内无有效数据)。

//堆的构建
#define SIZE 4

void HeapInit(Heap* hp)
{
	assert(hp);

	hp->data = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);
	if (hp == NULL) 
	{
		perror("mallo: ");
		exit(-1);
	}

	hp->capacity = SIZE;
	hp->size = 0;
}

3. 堆的销毁 (HeapDestroy)

free掉动态开辟的空间,使capacity 和 size 置 0(此时空间大小为0)

//堆的销毁
void HeapDestroy(Heap* hp)
{
	assert(hp);

	free(hp->data);
	hp->data = NULL;

	hp->capacity = hp->size = 0;
}

4. 堆的插入 (HeapPush)

将数据插入到堆的尾部(最后一个子节点后),然后与其父节点相比较,如果该节点小于其父节点(这里是小堆),交换两个节点的值,直到该节点为堆顶或其父节点小于该节点。

  • 假设该节点下标是 i,那么其父节点的小标是 ( i - 1 ) / 2

数据结构:堆的实现(C实现),数据结构,数据结构,c语言,算法

//交换
void swap(HPDataType* a, HPDataType* b)
{
	HPDataType tmp = *a;
	*a = *b;
	*b = tmp;
}

//向上调整 假设该节点是 i,父节点是 (i - 1) / 2
void AdjustUp(HPDataType* data, int child)
{
	int parent = (child - 1) / 2;

	while (child > 0)
	{
		if (data[child] < data[parent])
		{
			swap(&data[child], &data[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else 
		{
			break;
		}
	}
}


//堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);

	//检查容量
	if (hp->capacity == hp->size)
	{
		HPDataType* tmp = (HPDataType*)realloc(hp->data ,sizeof(HPDataType) * (hp->capacity * 2));
		if (tmp == NULL)
		{
			perror("realloc:");
			exit(-1);
		}

		hp->data = tmp;
		hp->capacity *= 2;
	}

	hp->data[hp->size] = x;
	hp->size++;

	//向上调整   传入数组和出入数据的下标
	//此处是小堆
	AdjustUp(hp->data, hp->size - 1);
}

5. 堆的删除 (HeapPop)

堆的删除是删除堆顶数据。
堆顶数据和堆的尾部数据交换,size 减一,然后将新的堆顶数据与其左右孩子节点的最小值比较,如果新堆顶数据大于左右孩子节点的最小值,交换数据,再次与新的左右孩子节点的最小值
比较。直到该数据小于左右孩子的最小值,或该数据超出有效数据范围。

  • 假设某个节点的下标是 i,其左孩子节点的下标:i * 2 + 1,其右孩子的下标:i * 2 + 2
  • 删除堆顶数据,不能挪到数据将堆顶数据覆盖。如果挪到数据,那么兄弟节点可能会变成父子节点,而兄弟节点之间并不保证大小关系,可能会破坏堆的结构(这里是会破坏小堆结构)。

数据结构:堆的实现(C实现),数据结构,数据结构,c语言,算法

//交换
void swap(HPDataType* a, HPDataType* b)
{
	HPDataType tmp = *a;
	*a = *b;
	*b = tmp;
}


//向下调整,假设该节点是 i, 右孩子节点是 2 * i + 1,左孩子节点是 2 * i + 2
void AdjustDown(HPDataType* data, int parent, int size)
{
	int child = parent * 2 + 1;

	while (parent < size)
	{
		//防止越界                    找左右孩子中最小的
		if (child + 1 < size && data[child] > data[child + 1])
		{
			child++;
		}

		if (child < size && data[parent] > data[child])
		{
			swap(&data[parent], &data[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}



//堆的删除  首元素 与 尾元素交换,新的堆顶在向下调整
void HeapPop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	
	hp->data[0] = hp->data[hp->size - 1];
	hp->size--;

	//向下调整
	AdjustDown(hp->data, 0, hp->size);
}

6. 取堆顶的数据 (HeapTop)

读取数组空间下标为0处即可。

//取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
	assert(hp);

	return hp->data[0];
}

7. 堆的数据个数 (HeapSize)

堆的结构中size表示此时堆中有效数据的个数,访问size即可。

//堆的数据个数
int HeapSize(Heap* hp)
{
	assert(hp);

	return hp->size;
}

8. 堆的判空 (HeapEmpty)

size表示堆的有效数据个数,如果size == 0,表示堆为空。

//堆的判空
bool HeapEmpty(Heap* hp)
{
	assert(hp);

	return hp->size == 0;
}

三、代码实现

//Heap.c   文件


#include "Heap.h"


//堆的构建
void HeapInit(Heap* hp)
{
	assert(hp);

	hp->data = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);
	if (hp == NULL) 
	{
		perror("mallo: ");
		exit(-1);
	}

	hp->capacity = SIZE;
	hp->size = 0;
}


//堆的销毁
void HeapDestroy(Heap* hp)
{
	assert(hp);

	free(hp->data);
	hp->data = NULL;

	hp->capacity = hp->size = 0;
}

//交换
void swap(HPDataType* a, HPDataType* b)
{
	HPDataType tmp = *a;
	*a = *b;
	*b = tmp;
}

//向上调整 假设该节点是 i,父节点是 (i - 1) / 2
void AdjustUp(HPDataType* data, int child)
{
	int parent = (child - 1) / 2;

	while (child > 0)
	{
		if (data[child] < data[parent])
		{
			swap(&data[child], &data[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}


//堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);

	//检查容量
	if (hp->capacity == hp->size)
	{
		HPDataType* tmp = (HPDataType*)realloc(hp->data ,sizeof(HPDataType) * (hp->capacity * 2));
		if (tmp == NULL)
		{
			perror("realloc:");
			exit(-1);
		}

		hp->data = tmp;
		hp->capacity *= 2;
	}

	hp->data[hp->size] = x;
	hp->size++;

	//向上调整   传入数组和出入数据的下标
	//此处是小堆
	AdjustUp(hp->data, hp->size - 1);
}



//向下调整,假设该节点是 i, 右孩子节点是 2 * i + 1,左孩子节点是 2 * i + 2
void AdjustDown(HPDataType* data, int parent, int size)
{
	int child = parent * 2 + 1;

	while (parent < size)
	{
		//防止越界                    找左右孩子中最小的
		if (child + 1 < size && data[child] > data[child + 1])
		{
			child++;
		}

		if (child < size && data[parent] > data[child])
		{
			swap(&data[parent], &data[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}



//堆的删除  首元素 与 尾元素交换,新的堆顶在向下调整
void HeapPop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	
	hp->data[0] = hp->data[hp->size - 1];
	hp->size--;

	//向下调整
	AdjustDown(hp->data, 0, hp->size);
}



//取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
	assert(hp);

	return hp->data[0];
}




//堆的数据个数
int HeapSize(Heap* hp)
{
	assert(hp);

	return hp->size;
}



//堆的判空
bool HeapEmpty(Heap* hp)
{
	assert(hp);

	return hp->size == 0;
}
//Heap.h  文件

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

#define SIZE 4

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* data;
	int capacity;
	int size;
}Heap;


//堆的构建
void HeapInit(Heap* hp);

//堆的销毁
void HeapDestroy(Heap* hp);

//堆的插入
void HeapPush(Heap* hp, HPDataType x);

//堆的删除
void HeapPop(Heap* hp);

//取堆顶的数据
HPDataType HeapTop(Heap* hp);

//堆的数据个数
int HeapSize(Heap* hp);

//堆的判空
bool HeapEmpty(Heap* hp);


总结

以上就是我对于堆的实现!!!
数据结构:堆的实现(C实现),数据结构,数据结构,c语言,算法文章来源地址https://www.toymoban.com/news/detail-645319.html

到了这里,关于数据结构:堆的实现(C实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】堆:堆的构建,堆的向上调整算法,堆的向下调整算法、堆排序

    目录 一、堆的定义 1、堆的定义: 2、根节点与其左、右孩子间的联系   二、堆的创建 1、堆的向下调整算法  2、堆的向上调整算法  三、堆排序 1、堆的定义: 堆可以被看作是 一棵 完全二叉树 的 数组 对象 。即在 存储结构上是数组,在逻辑结构上是一棵完全二叉树 。在

    2024年01月22日
    浏览(43)
  • 数据结构:堆的实现

    如果有一个关键码的集合 K = { k1 ,k2 ,k3 ,…,kn },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且 k(i)  k(i*2+1) 和 k(i)  k(i*2+2), i = 0 , 1 , 2…,则称为小堆 ( 或大堆 ) 。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小

    2024年02月13日
    浏览(35)
  • 数据结构---堆的实现

    前言 一、什么是堆? 二、 堆的实现 1. 堆的结构  2. 接口实现 总结 堆(Heap)是计算机科学中一类特殊的数据结构,是最高效的优先级队列。堆通常是一个可以被看做一棵完全二叉树的数组对象。 现实中我们通常把 堆(一种二叉树) 使用 顺序结构的数组 来存储, 大根堆 :根节

    2024年02月02日
    浏览(39)
  • 数据结构之堆的结构与实现

    目录 一、堆的概念及结构 1.1堆的概念  1.2堆的性质 1.3堆的结构 二、堆的实现 2.1堆向下调整算法(父亲与孩子做比较)  2.2堆的向上调整算法(孩子与父亲做比较) 2.3堆的创建(向下建堆)  2.4向下建堆的时间复杂度 2.5堆的插入 2.6堆的删除 2.7堆的完整代码实现 三、堆的应

    2024年02月08日
    浏览(40)
  • 数据结构—小堆的实现

    前言:前面我们已经学习了二叉树,今天我们来学习堆,堆也是一个二叉树,堆有大堆有小堆,大堆父节点大于子节点,小堆父节点总小于子节点,我们在学习C语言的时候也有一个堆的概念,那个堆是操作系统中的堆,与我们今天所学的堆全然不同。我们就来实现下小堆。

    2024年02月05日
    浏览(34)
  • 数据结构:堆的实现(C实现)

    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 当一颗完全二叉树用顺序表来存储时,其被称为堆。 堆总是一棵完全二叉树 堆的某个节点的值总是不大于(大堆)或不小于(小堆)其父节点的值 其可以被用来解决top k 问题 或 堆排序 下面就是要实现的堆的功能 重点在

    2024年02月13日
    浏览(36)
  • 数据结构——二叉树(堆的实现)

    目录   树概念及结构 树的相关概念 树的表示  二叉树的概念及结构   堆 堆的实现   结构体建立 初始化   添加元素  打印堆  删除堆首元素  返回首元素  判断是否为空 空间销毁  刷题找工作的好网站——牛客网 牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,

    2024年02月11日
    浏览(45)
  • 【数据结构之堆的实现】

    前言: 前篇学习了 数据结构之树和二叉树的基本概念知识,那么这篇继续学习怎么实现基本的操作。所以先建议看完上篇知识点,才有助于消化知识和理解。 / 知识点汇总 / 概念 :堆(Heap)是计算机科学中一类特殊的数据结构,是最高效的优先级队列。堆通常是一个可以被看

    2024年01月19日
    浏览(43)
  • 【数据结构】堆的实现及应用

    简单不先于复杂,而是在复杂之后 。 1.1 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。 而完全二叉树更适合使用顺序结构存储。 现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系

    2024年02月21日
    浏览(48)
  • 【数据结构】结构实现:顺序存储模式实现堆的相关操作

    🚩 纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:数据结构 🔥该文章着重讲解了使用顺序结构实现堆的插入和删除等操作。  二叉树的顺序存储是指将二叉树中的所有节点按照一定的顺序(一层一层)存储到一个数组中。  我们可以通过数组下标来表示

    2024年02月08日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包