iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言详解如何实现堆及堆的结构与接口
  • 870
分享到

C语言详解如何实现堆及堆的结构与接口

2024-04-02 19:04:59 870人浏览 八月长安
摘要

目录一、堆的结构及实现(重要)1.1 二叉树的顺序结构1.2 堆的概念及结构1.3 堆的实现1.3.1 堆的向下调整算法1.3.2 向下调整算法的时间复杂度1.3.3 堆的创建(向下

一、堆的结构及实现(重要)

1.1 二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。在现实中我们通常把堆 (一种完全二叉树) 使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

1.2 堆的概念及结构

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。堆总是满足下列性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值;
  • 堆总是一棵完全二叉树。

堆是非线性数据结构,相当于一维数组,有两个直接后继。

【大根堆和小根堆】:

根结点最大的堆叫做大根堆,树中所有父亲都大于或等于孩子。

根结点最小的堆叫做小根堆,树中所有父亲都小于或等于孩子。

【思考】这个大根堆和小根堆有什么特点呢?

最值总在 0 号位,根据这个特点我们就可以做很多事情,比如TopK问题 (在一堆数据里面找到前 K 个最大 / 最小的数),生活中也有很多实例,比如点餐软件中有上千家店铺,我想选出该地区好评最多的十家川菜店,我们不用对所有数据排序,只需要取出前 K 个最大 / 最小数据。使用堆排序效率也更高。

1.3 堆的实现

1.3.1 堆的向下调整算法

下面给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:该节点的左右子树必须是一个 (大 / 小) 堆,才能调整。

int array[] = { 27,15,19,18,28,34,65,49,25,37 }; // 根节点的左右子树都是小堆

上面的数组,因为根节点的左右子树都是小堆,所以我们从根节点开始调整,将其调成小堆。

向下调整算法思路(调成小堆):

从根节点开始,不断往下调。

选出根节点的左右孩子中「最小的孩子」,与「父亲」进行比较。

  • 如果父亲小于孩子,就不需处理了,整个树已经是小堆了。
  • 如果父亲大于孩子,就跟父亲交换位置,并将原来小的孩子的位置当成父亲继续向下进行调整,直到调整到叶子结点为止。

向下调整算法过程演示(调成小堆,把大的节点往下调整):

向下调整算法代码:

// 向下调整算法,建小堆,把大的节点往下调整
// 前提是:左右子树都是小堆
void AdjustDown(int* a, int size, int parent)
{
	// 指向左孩子,默认左孩子最小
	int child = parent * 2 + 1;
	while (child < size)
	{
		// 1. 选出左右孩子最小的那个,先判断右孩子是否存在
		if (child + 1 < size && a[child] > a[child + 1])
		{
			child++; // 指向右孩子
		}
		// 2. 最小的孩子与父亲比较
		if (a[parent] > a[child]) // 如果父亲大于孩子
		{
			// 父亲与孩子交换位置
			Swap(&a[parent], &a[child]);
			// 更新父子下标,原先最小的孩子作为父亲,继续往下调
			parent = child;
			child = parent * 2 + 1;
		}
		else // 如果父亲小于孩子,说明已经为小堆了,停止调整
		{
			break;
		}
	}
}

1.3.2 向下调整算法的时间复杂度

我们以满二叉树计算,最坏情况下,向下调整算法最多进行满二叉树的高度减1次比较,则说明向下调整算法最多调整满二叉树的高度减1次,n 个节点的满二叉树高度为 log2(n+1),估算后所以时间复杂度为 O(log2n)。

1.3.3 堆的创建(向下调整)

下面给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但不是一个堆,我们需要通过算法把它构建成一个堆。如果根节点左右子树不是一个 (大 / 小) 堆,我们应该怎么调整呢?

我们倒着调整,从下到上,从「倒数第一个非叶子节点的子树」开始,依次遍历完所有非叶子节点,分别对每个子树进行「向下调整」成 (大 / 小) 堆,一直调整到「根节点」,就可以建成一个 (大 / 小) 堆。

为什么要倒着调整呢?因为这样我们可以把「倒数第一个非叶子节点的子树」的左右子树看成是一个 (大 / 小) 堆,此时才能去使用向下调整算法。比如下图中的黄色填充的子树,3 的左子树 6 就可以看成是一个大堆。

【实例】:将下面的数组建成一个大堆

int a[] = { 1,5,3,8,7,6 };

建堆过程演示(以建大堆为例):从下到上,依次遍历完所有非叶子节点,分别对每个子树进行向下调整。

依次对 每一步 中,方框内的树 进行 向下调整 为一个 大堆。

建堆代码:

// 交换函数
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
// 向下调整算法,建大堆,把小的节点往下调
// 前提是:左右子树都是大堆
void AdjustDown(int* a, int size, int parent)
{
	// 指向左孩子,默认左孩子最大
	int child = parent * 2 + 1;
	while (child < size)
	{
		// 1. 选出左右孩子最大的那个,先判断右孩子是否存在
		if (child + 1 < size && a[child] < a[child + 1])
		{
			child++; // 指向右孩子
		}
		// 2. 最大的孩子与父亲比较
		if (a[parent] < a[child]) // 如果父亲小于孩子
		{
			// 父亲与孩子交换位置
			Swap(&a[parent], &a[child]);
			// 更新父子下标,原先最大的孩子作为父亲,继续往下调
			parent = child;
			child = parent * 2 + 1;
		}
		else // 如果父亲大于孩子,说明已经为大堆了,停止调整
		{
			break;
		}
	}
}
void HeapSort(int* a, int size)
{
    
	int parent = ((size - 1) - 1) / 2; // 最后一个叶子节点的父亲的下标
	for (int i = parent; i >= 0; i--)  // 从下到上,依次遍历完所有子树,分别对其进行调整
	{
		AdjustDown(a, size, i);
	}
    
    // 下面是排升序:
	int end = size - 1; // 记录堆中最后一个元素的下标
	while (end > 0)
	{
		Swap(&a[0], &a[end]);  // 将堆顶元素和堆中最后一个元素交换,把最大的数(堆顶)放到最后
		AdjustDown(a, end, 0); // 不看最后一个数,从根节点开始,对前面的数进行向下调整成大堆
		end--;
	}
}

1.3.4 堆排序

排升序 --> 建大堆:

【思考】排升序,建小堆可以吗?-- 可以是可以,但没啥意思。

首先对 n 个数建小堆,选出最小的数,接着对剩下的 n-1 个数建小堆,选出第2小的数,不断重复上述过程……。建 n 个数的堆时间复杂度是O(N),所以上述操作时间复杂度为O(N2),效率太低,尤其是当数据量大的时候,效率更低,同时堆的价值没有被体现出来,还不如用直接排序。

【最佳方法】排升序,因为数字越来越大,需要找到最大的数字,得建大堆

  • 首先对 n 个数建大堆。
  • 将最大的数(堆顶)和最后一个数交换,把最大的数放到最后。
  • 前面 n-1 个数的堆结构没有被破坏(最后一个数不看做堆里面的),根节点的左右子树依旧是大堆,所以我们进行一次向下调整成大堆即可选出第2大的数,放到倒数第二个位置,然后重复上述步骤……。

【时间复杂度】:建堆时间复杂度为O(N),向下调整时间复杂度为O(log2N),这里我们最多进行N-2次向下调整,所以堆排序时间复杂度为O(N*log2N),效率是很高的。

排降序 --> 建小堆:

【最佳方法】排降序,因为数字越来越小,需要找到最小的数字,得建小堆

  • 首先对 n 个数建小堆。
  • 将最小的数(堆顶)和最后一个数交换,把最小的数放到最后。
  • 前面 n-1 个数的堆结构没有被破坏(最后一个数不看做堆里面的),根节点的左右子树依旧是小堆,所以我们进行一次向下调整成小堆即可选出第2小的数,放到倒数第二个位置,然后重复上述步骤……。
  • 【时间复杂度】:建堆时间复杂度为O(N),向下调整时间复杂度为O(log2N),这里我们最多进行N-2次向下调整,所以堆排序时间复杂度为O(N*log2N),效率是很高的。

1.3.5 建堆的时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明,计算起来比较好算(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):

建堆要从倒数第一个非叶子节点开始调整,也即是从倒数第二层开始调,可得出时间复杂度公式:

T ( n ) = ∑ ( 每 层 节 点 数 ∗ ( 堆 的 高 度 − 当 前 层 数 ) )

所以,建堆的时间复杂度为O(N)。

【上面学了那么多,这里小小总结一下】

  • 堆的向下调整算法就是,在该节点左右子树都是一个小/大堆的前提下,将以该节点为根的树调整成一个小/大堆。
  • 堆的创建就是倒着调整,从下到上,从倒数第一个非叶子节点的子树开始,依次遍历完所有子树,分别对其进行向下调整。
  • 时间复杂度:堆的向下调整算法为O(log2N),堆的创建为O(N)。

二、堆的相关接口实现(以大堆为例)

首先新建一个工程( 博主使用的是 VS2019 )

  • Heap.h(堆的类型定义、接口函数声明、引用的头文件)
  • Heap.c(堆接口函数的实现)
  • Test.c(主函数、测试堆各个接口功能)

Heap.h 头文件代码如下:

#pragma once
#include<stdio.h>   // printf, perror
#include<stdbool.h> // bool
#include<assert.h>  // assert
#include<stdlib.h>  // malloc, free
#include<string.h>  // memcpy
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a; // 指向动态开辟的数组
	int size;      // 数组中有效元素个数
	int capacity;  // d容量
}Heap;
// 交换函数
void Swap(HPDataType* a, HPDataType* b);
// 向下调整函数(调成大堆,把小的往下调)
void AdjustDown(HPDataType* a, int size, int parent);
// 向上调整函数(调成大堆,把大的往上调)
void AdjustUp(HPDataType* a, int child);
// 初始化堆
void Heapinit(Heap* PHP, HPDataType* arr, int n);
// 销毁堆
void HeapDestroy(Heap* php);
// 插入元素(插入到堆的末尾),插入后并保持它依然是堆
void HeapPush(Heap* php, int x);
// 删除堆顶元素,删除后保持它依然是堆
void HeapPop(Heap* php);
// 获取堆顶元素,也即是最值
HPDataType HeapTop(Heap* php);
// 判断堆是否为空,为空返回true,不为空返回false
bool HeapEmpty(Heap* php);
// 获取堆中有效元素个数
int HeapSize(Heap* php);
// 打印堆
void HeapPrint(Heap* php);

2.1 堆的初始化

堆的初始化,首先需要实现一个向下调整算法:

// 交换函数
void Swap(HPDataType* a, HPDataType* b)
{
	HPDataType tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}
// 向下调整算法(调成大堆,把小的往下调)
void AdjustDown(HPDataType* a, int size, int parent)
{
	// 左孩子下标,初始默认左孩子最大
	int child = parent * 2 + 1;
	while (child < size)
	{
		// 选出左右孩子最大的那个,先判断右孩子是否存在
		if (child + 1 < size && a[child] < a[child + 1])
		{
			child++; // 右孩子最大
		}
		// 最大的孩子与父亲比较
		if (a[parent] < a[child]) // 如果父亲小于孩子
		{
			// 父亲与孩子交换位置
			Swap(&a[parent], &a[child]);
			// 更新父子下标,原先最大的孩子作为父亲,继续往下调
			parent = child;
			child = parent * 2 + 1;
		}
		else // 如果父亲大于孩子,说明已经为大堆了,停止调整
		{
			break;
		}
	}
}

堆的初始化代码:

// 初始化堆,用一个给定的数组来初始化
void HeapInit(Heap* php, HPDataType* arr, int n)
{
	assert(php); // 断言
	// 动态开辟n个空间
	php->a = (HPDataType*)malloc(sizeof(HPDataType) * n);
	if (php->a == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	// 把给定数组的各元素值拷贝过去
	memcpy(php->a, arr, sizeof(HPDataType) * n);
	php->size = php->capacity = n;
	// 建堆(建大堆)
	int parent = ((php->size - 1) - 1) / 2; // 倒数第一个非叶子节点下标
	for (int i = parent; i >= 0; i--) // 从下到上,依次遍历完所有子树,分别对其进行调整
	{
		AdjustDown(php->a, php->size, i);
	}
}

2.2 堆的销毁

// 销毁堆
void HeapDestroy(Heap* php)
{
	assert(php);
	free(php->a); // 释放动态开辟的空间
	php->a = NULL;
	php->size = php->capacity = 0;
}

2.3 堆的插入

先插入一个新元素到数组的尾上,从插入的新元素开始,进行向上调整算法,直到满足(大/小)堆。

堆的插入过程演示:

堆的插入,首先需要实现一个向上调整算法:

// 向上调整算法(调成大堆,把大的往上调)
void AdjustUp(HPDataType* a, int child)
{
	// 父节点的下标
	int parent = (child - 1) / 2;
	//while (parent >= 0) parent不会小于0
	while (child > 0)
	{
		// 孩子与父亲进行比较
		if (a[child] > a[parent]) // 如果孩子大于父亲
		{
			// 孩子与父亲交换
			Swap(&a[child], &a[parent]);

			// 更新父子下标,原先父亲作为孩子,继续往上调
			child = parent;
			parent = (child - 1) / 2;
		}
		else // 如果孩子小于父亲,说明已经为大堆了,停止调整
		{
			break;
		}
	}
}

堆的插入代码:

// 插入元素(插入到堆的末尾),插入后并保持它依然是堆
void HeapPush(Heap* php, int x)
{
	assert(php);
	// 先检查空间是否已满
	if (php->capacity == php->size)
	{
		// 增容两倍
		php->capacity *= 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity);
		if (tmp != NULL)
		{
			php->a = tmp;
			tmp = NULL;
		}
	}
	// 插入元素
	php->a[php->size] = x;
	php->size++;
	// 从插入的元素开始,进行向上调整,保持它依然是堆
	AdjustUp(php->a, php->size - 1);
}

2.4 堆的删除

  • 将堆顶元素和最后一个元素交换(这样就变成尾删了,很方便)
  • 删除堆中最后一个元素
  • 从根节点开始,对剩下元素进行向下调整,调成(大/小)堆

堆的删除过程演示:

堆的插入,首先需要实现一个向下调整算法:前面已经实现过了,这里就不展示了。

堆的删除代码:

// 删除堆顶元素,删除后保持它依然是堆
void HeapPop(Heap* php)
{
	assert(php);
	assert(!HeapEmpty(php)); // 堆不能为空
	// 将堆顶元素和最后一个元素交换
	Swap(&php->a[0], &php->a[php->size - 1]);
	// 删除堆中最后一个元素
	php->size--;
	// 从根节点开始,对剩下元素进行向下调整成大堆,保持它依然是堆
	AdjustDown(php->a, php->size, 0);
}

2.5 获取堆顶元素

// 获取堆顶元素,也即是最值
HPDataType HeapTop(Heap* php)
{
	assert(php);
	assert(!HeapEmpty(php)); // 堆不能为空
	return php->a[0];
}

2.6 堆的判空

// 判断堆是否为空,为空返回true,不为空返回false
bool HeapEmpty(Heap* php)
{
	assert(php);
	return php->size == 0;
}

2.7 找出堆中前k个最大元素

堆的相关接口实现好了,因为是大堆,所以我们可以很方便的来找出堆中前 k 个最大元素。

这里要和前面的堆排序区分开哦,这里我们并不是在堆中对所有元素排好序。

void TestHeap()
{
	int a[] = { 1,5,3,8,7,6 };
	Heap hp;
	HeapInit(&hp, a, sizeof(a) / sizeof(a[0])); // 初始化堆
	int k = 0;
	scanf("%d", &k);
	printf("找出堆中前%d个最大元素:\n", k);
	while (!HeapEmpty(&hp) && k--)
	{
		printf("%d ", HeapTop(&hp)); // 获取堆顶元素
		HeapPop(&hp); // 删除堆顶元素
	}
	printf("\n");
}

运行结果:

2.8 堆的创建(向上调整)

下面给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但不是一个堆,我们需要通过「向上调整算法」把它构建成一个堆。如果根节点左右子树不是一个 (大 / 小) 堆,我们应该怎么调整呢?

我们从上到下,从「第一个节点(也就是根节点)的左孩子」开始,依次遍历完所有节点,分别对每个节点进行「向上调整」,一直到「最后一个节点」,就可以建成一个 (大 / 小) 堆。

我们把数组中的「第一个元素」看作是一个「堆」,剩余的元素依次插入到这个「堆」中。前面我们也实现了堆的插入接口,原理就是向上调整。

// 向上调整算法建堆
void CreateHeap(int* a, int size)
{
	// 把第一个元素看作是堆,剩余的元素依次插入堆中
	for (int i = 1; i < size; i++)
	{
		AdjustUp(a, i);
	}
}

到此这篇关于C语言详解如何实现堆的结构与接口的文章就介绍到这了,更多相关C语言堆的结构与接口内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言详解如何实现堆及堆的结构与接口

本文链接: https://www.lsjlt.com/news/147116.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言详解如何实现堆及堆的结构与接口
    目录一、堆的结构及实现(重要)1.1 二叉树的顺序结构1.2 堆的概念及结构1.3 堆的实现1.3.1 堆的向下调整算法1.3.2 向下调整算法的时间复杂度1.3.3 堆的创建(向下...
    99+
    2022-11-13
  • C语言怎么实现堆及堆的结构与接口
    本文小编为大家详细介绍“C语言怎么实现堆及堆的结构与接口”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言怎么实现堆及堆的结构与接口”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、堆的结构及实现(重要)1....
    99+
    2023-06-30
  • C语言数据结构之堆、堆排序的分析及实现
    目录 1.堆的概念结构及分类1.2堆的分类1.2.1 大堆1.2.2 小堆2. 堆的主要接口3.堆的实现3.1 堆的初始化 HeapInit3.2 堆的销毁 HeapDes...
    99+
    2022-11-13
  • C语言数据结构二叉树之堆的实现和堆排序详解
    目录一、本章重点二、堆2.1堆的介绍2.2堆的接口实现三、堆排序一、本章重点 堆的介绍堆的接口实现堆排序 二、堆 2.1堆的介绍 一般来说,堆在物理结构上是连续的数组结构,在逻辑结构...
    99+
    2022-11-13
  • C语言堆与二叉树的顺序结构与实现
    目录一. 二叉树的顺序结构二. 堆的概念及结构三. 堆的实现四. 堆排序(具有缺陷型)一. 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全...
    99+
    2022-11-13
  • C语言 深入解读数据结构之堆的实现
    堆的概念与结构 概念:如果有一个关键码的集合K={ k0,k1 ,k2 ,…,kn-1 },把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足K i<=K ...
    99+
    2022-11-12
  • C语言数据结构堆的基本操作实现
    目录1.基本函数实现a.代码1(向下调整)b.代码2(向上调整)c.代码3(交换)2.建堆 3.插入数据4. 删除数据5.获取堆顶的数据6.堆的数据个数7.判空8.打印9.销毁10....
    99+
    2022-11-12
  • Java数据结构之最小堆和最大堆的原理及实现详解
    目录一、前言二、堆的数据结构三、堆的代码实现1. 实现介绍2. 入堆实现3. 出堆实现4. 小堆实现5. 大堆实现一、前言 堆的历史 堆的数据结构有很多种体现形式,包括;2-3堆、B...
    99+
    2022-11-13
  • C语言数据结构堆的基本操作实现是怎样的
    本篇文章为大家展示了C语言数据结构堆的基本操作实现是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1.基本函数实现a.代码1(向下调整)void AdjustDown(DateTyp...
    99+
    2023-06-21
  • C语言数据结构与算法之队列的实现详解
    目录队列的概念及结构队列的实现Queue.hQueue.cTest.c队列的概念及结构 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FI...
    99+
    2022-11-13
    C语言数据结构 队列 C语言 队列实现 C语言 队列
  • C语言顺序表的基本结构与实现思路详解
    目录一、顺序表的概念与结构1、线性表的解释2、顺序表概念解释二、顺序表的思路及代码实现详解1.静态顺序表的实现2.动态顺序表思路及代码实现2.1 动态顺序表的整体思路2.2 定义结构...
    99+
    2023-02-13
    C语言顺序表 C语言顺序表的创建
  • C语言多维数组数据结构的实现详解
    目录数据结构之多维数组各基本操作函数原型说明 各基本操作的具体实现测试分析思考与小结1、 对数组的再认识2、调试过程中遇到的问题及解决方案3、算法的时间复杂度分析总结数据结构之多维数...
    99+
    2022-11-12
  • C语言详解实现链式二叉树的遍历与相关接口
    目录前言一、二叉树的链式结构二、二叉树的遍历方式1.1 遍历方式的规则1.2 前序遍历1.3 中序遍历1.4 后序遍历1.5 层序遍历三、二叉树的相关接口实现3.1 二叉树节点个数3...
    99+
    2022-11-13
  • 详解C语言结构体中的char数组如何赋值
    目录前景提示一.char数组类型的处理1.结构体初始化2.结构体内数据赋值(简单法)二.char数组指针类型的处理1.结构体初始化2.结构体内数据赋值3.结构体内输出数据三.全部代码...
    99+
    2022-11-13
  • C语言位段(位域)机制结构体的特殊实现及解析
    目录概念内存分配位段跨平台问题作用Tip应用场景概念 什么是位段? 位段又称为位域,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员就叫做称为位段( ...
    99+
    2022-11-13
  • 如何进行数据结构C语言链表的实现
    这篇文章将为大家详细讲解有关如何进行数据结构C语言链表的实现,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前言需要用到的函数库#include<stdio.h>#include&...
    99+
    2023-06-22
  • Go 语言数据结构如何实现抄一个list示例详解
    目录前言list是个啥list结构Init & NewInsertAfter & InsertBefore & PushBack & PushFron...
    99+
    2023-05-16
    Go 语言数据结构list Go list
  • C语言如何实现通用数据结构中的通用椎栈
    今天就跟大家聊聊有关C语言如何实现通用数据结构中的通用椎栈,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。为大家分享了C语言实现通用数据结构之通用椎栈的具体代码,具体内容如下这是在通用...
    99+
    2023-06-21
  • C语言如何实现通用数据结构中的通用集合
    本篇文章为大家展示了C语言如何实现通用数据结构中的通用集合,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。这是在通用链表的基础上实现的集合,关于链表的实现参见:C语言实现通用数据结构之通用链表注意集合...
    99+
    2023-06-21
  • 详解利用C语言如何实现简单的内存池
    前言 在编程过程中,尤其是对于C语言开发者,其实编程就是在使用内存,不停地变化内存中的数据。当我们想开辟一片新的内存使用时,就会使用malloc实现。但是通过查阅很多资料,发现频繁的...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作