堆的实现及应用

堆的原理实现详解以及堆的应用 文章目录堆是什么堆的存储方式插入结点删除结点堆排序代码实现 堆是什么   堆(heap)本质上就是一棵完全二叉树,只不过这棵完全二叉树有点特别,能够被称为堆的二叉树,除了它必须要是一棵完全二叉树外,它的每一个结点都必须大于或者小于其子节点。 解释一下就是对于树中的所有的结点都至少有一棵子树,对于这个结点的子树上所有的结点都必须要大于或者小于其父节点。因此,堆也是个递归的定义,通常,我们将结点都大于或者等于子树所有结点的堆称为最大堆 ;将结点都小于或者等于子树所有结点的堆称为最小堆 。如下图所示: 阅读详情

目录

 堆的概念及结构

二叉树的存储结构

堆向下调整算法

堆的创建

建堆时间复杂度

堆的插入

堆的删除

堆的实现代码

堆实现的心得体会

堆的应用

 堆排序

TOP-K问题


 堆的概念及结构

堆的逻辑结构是完全二叉树,物理存储的结构是顺序表

堆的性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树

二叉树的存储结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树或满二叉树,因为不是完全二叉树会有空

间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

父子结点下标的规律关系

Leftchid=parent*2+1

Rightchid=parent*2+2

Parent=(child-1)/2 不区分左右孩子。

非完全二叉树就不适合数组存储结构,适合链式结构存储。

堆向下调整算法
 

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

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;//child++的前提是child+1没有越界

		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}

	}
	

}

堆的创建

下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算
法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的
子树开始调整,一直调整到根节点的树,就可以调整成堆。

新的建堆方法

1左右子树都是小堆,向下调整即可,能变成小堆。

2如果不是,倒着调整,(目的是把左右子数都调成小堆)叶子不需要调,从倒数第一个非叶子结点开始调,也是最后一个节点的父结点。

最后一个位置是n-1,(n-1-1)/2是其父结点的下标,也是第一个非叶子结点。  

针对每一个非叶结点都能找到其子结点进行向下调整,从而使这个非叶结点所构成的子数变成小堆,随着非叶结点向上遍历与每次的向下调整,最终使左右子数都变成小堆。

   只写一个向下调整问题就能解决。效率高 时间复杂度O(N)

它的调整次数是随非叶结点的位置的变化而变化的。

建堆时间复杂度

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

向下调整建堆的时间复杂度

第h层:2^(h-1)个结点

第h-1层:2^(h-2)个结点

T(h)是建堆的累积调整次数

T(h)=2^(h-2)*1+2^(h-3)*2+………………….+2^0 *(h-1)等差乘等比 (错位相减法)

T(h)=2^h -1-h

 H是树的高度 N是树的节点个数

满二叉树:2^h-1=N  àh=log(N+1)

T(h)=2^h -1-h =N-log(N+1)=T(N)

因此时间是复杂度约为O(N)

向上调整建堆的时间复杂度

从第二层开始的原因:如果是从第一层开始的话:结点之间的伦理关系全都乱了。

从第二层往下走逐渐向上调整 二叉树的最后一层结点占一半

T(h)= 2^1*1+ 2^2*2+2^3*3………………………..+2^(h-1)*(h-1)

T(h) = -(2^h-1)+2^h*(h-1)+2^0

T(N)= -N+(N+1)*(log(N+1)-1)

与向下调整对比 一个多乘多 一个少乘多。且多了一行最多需要计算的一行,且最后一行时间复杂度就已经是O(N*logN)了。

总体的向上调整的算法复杂度O(N*logN)

选数的时间复杂度O(N*logN)

堆的插入

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。

void Adjustup(HPDataType* a, int child)//孩子找父母 向上查找
{ 
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;

		}
		else
		{
			break;
		}
	}
}




void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->size == php->Capacity)
	{
		int newCapacity = php->Capacity == 0 ? 4 : php->Capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);

		}
		php->a = tmp;
		php->Capacity = newCapacity;

	}
	php->a[php->size] = x;
	php->size++;

	Adjustup(php->a, php->size-1);



}

堆的删除

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。

void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	Adjustdown(php->a, php->size, 0);

}

堆的实现代码

#include<assert.h>
#include<stdbool.h>
#include<time.h>

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* a;
	int size;
	int Capacity;

}HP;

void HeapInit(HP* php);
void HeapDestroy(HP* php);
void HeapPush(HP* php, HPDataType x);
void HeapPop(HP* php);
HPDataType HeapTop(HP* php);
size_t HeapSize(HP* php);
bool HeapEmpty(HP* php);
void Swap(HPDataType* p1, HPDataType* p2);
void Adjustup(HPDataType* a, int child);
void Adjustdown(HPDataType* a, int size, int parent);

#include"Heap.h"

void HeapInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->Capacity = 0;

}
void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = 0;
	php->Capacity = 0;
	
}
void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;

}

void Adjustup(HPDataType* a, int child)//孩子找父母 向上查找
{ 
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;

		}
		else
		{
			break;
		}
	}
}




void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->size == php->Capacity)
	{
		int newCapacity = php->Capacity == 0 ? 4 : php->Capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);

		}
		php->a = tmp;
		php->Capacity = newCapacity;

	}
	php->a[php->size] = x;
	php->size++;

	Adjustup(php->a, php->size-1);



}
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;//child++的前提是child+1没有越界

		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}

	}
	

}


void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	Adjustdown(php->a, php->size, 0);

}

HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}
size_t HeapSize(HP* php)
{
	assert(php);
	return php->size;

}
bool HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;

}

堆实现的心得体会

1 首先堆与顺序表最大的区别就是在于逻辑结构上的区别 物理上的存储是没有区别的

逻辑结构表现在数组的元素(结点)之间的伦理关系(连接关系)数字关系(大小关系)

2结构决定功能 因此在pop和push这两个功能上,堆与顺序表的差异是巨大的,且pop和push互为逆运算,因此在函数实现上也表现是相反的,push是在叶节点(最底部)增加元素,本身是child,是通过child找parent,逐渐向上做“互换”的运算,child靠parent自我运算向上跑,最后找到头结束,而pop是删除头元素(根结点),通过parent找child,逐渐向下做“互换”运算,parent靠child自我运算往下跑,直到parent的child找到尾。

因此在两个“Adjust”的传参时,都要传HP* 一个传child ,一个传parent。一个传size,一个不要传。因为头坐标为0.

堆的应用

 堆排序
 

1. 建堆
升序:建大堆
降序:建小堆
2. 利用堆删除思想来进行排序
建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。

void Heapsort(int* a, int n)
{
	//建大堆
	//向上调整算法 时间复杂度NlogN
	/*for (int i = 1; i >= 0; i++)
	{
		Adjustup(a, 1);

	}*/

	//向下调整算法
	int end = n - 1;
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		Adjustdown(a, n, i);


	}
	//调整成大堆之后在数组中实际上是降序排列的,所以要借助删除函数的思想,进行交换操作

	while (end > 0)
	{
		Swap(&a[end], &a[0]);
		Adjustdown(a, end, 0);//首尾元素交换之后,新的尾元素就是本次操作的最大元素,应将其排除堆,所以这里end=n-1正好是排除堆后新的size
		--end;
	}

}

TOP-K问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
1. 用数据集合中前K个元素来建堆
前k个最大的元素,则建小堆
前k个最小的元素,则建大堆
2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

具体思考:

1读取前K个值,建立K个树的小堆

2、依次再读取后面的值,跟堆顶比较,如果比堆顶大,替换对顶进栈(替换堆顶值,再向下调整) 用小堆的精髓就是最大的前K个在进堆时,一定有比上来给的前K个要大(个体与个体比),一定能够进堆,然后较大的数会因为向下调整算法不断下沉。

空间复杂度就是k大小的堆 

时间复杂度:O(N*logK)

void CreateNDate()
{
	// 造数据
	int n = 10000000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (int i = 0; i < n; ++i)
	{
		int x = (rand() + i) % 10000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}


void HeapTopK(const char* file,int k)
{
	FILE* fout = fopen(file,"r");

	if (fout == NULL)
	{
		perror("fopen fail");
		return;
	}

	int* minheap = (int*)malloc(sizeof(int)*k);
	if (minheap == NULL)
	{
		perror("malloc fail");
		return;
	}

	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &minheap[i]);
		Adjustup(minheap, i);

	}
	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF)
	{
		/*if (x > 10000000)
		{
			int bb = 0;
		}*/
		if (x >= minheap[0])
		{
			minheap[0] = x;
			Adjustdown(minheap, k, 0);
		}
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", minheap[i]);

	}
	printf("\n");
	free(minheap);
	fclose(fout);
}

C++实现斐波那契堆及其应用 斐波那契堆是一种优先队列,每个节点维护若干子节点和一个度量值,即子节点的数量。它在堆结构中实现了动态数组的功能,对某些操作如删除最小元素和合并堆提供了优秀的摊还性能。在斐波那契堆的实现过程中,代码的编写既需要体现数据结构的设计理念,又要确保操作的效率。接下来,我们将深入探讨斐波那契堆的关键代码实现,并提出整体架构的优化建议。斐波那契堆的完整代码包括多个组件,如节点类,堆类以及操作方法。代码应该遵循模块化设计,使得各部分功能清晰,易于理解和维护。 阅读详情

相关推荐

斐波那契堆的C语言高效实现及应用

本文还有配套的精品资源,点击获取 简介:斐波那契堆是一种优先队列数据结构,适用于图算法如Dijkstra和Prim算法。本项目详细探讨了斐波那契堆的构成、操作及其C语言实现,包括插入、合并、提取最小元素、减小键值和删除操作。项目中定义了堆节点的结构体并维护堆的全局状态,同时实现了必要的操作函数,采用优化技巧确保性能。斐波那契堆能够高效地处理优先级队列问题,提供给开发者强大的...

weixin_42576804的博客 1450

堆的实现以及应用

👀👀👀👀👀👀🌹欢迎大家三连关注,一起学习,一起进步!!💓。

bushibrnxiaohaij的博客 1216

堆和优先队列的实现与应用

本文深入探讨了堆和优先队列的概念、性质和应用。堆是一种特殊的完全二叉树,它在数据结构中占有重要的地位。我们首先通过堆的形状和内容属性来理解其本质,接着讨论了堆在内存中的实现,包括节点编号方法、堆数组的特征以及插入和删除操作的算法。最后,我们探讨了如何在不同编程语言中实现堆,并提供了相应的示例代码。

weixin_31800911的博客 451

堆的实现+堆的应用(堆排序和Topk)

又是一万字的堆啊,你喜不喜欢

adcxhw的博客 1405

ABB机器人姿态与四元数(笔记)

通常使用机器人作业时,机器人的法兰轴(5轴)往往是垂直与作业平面的,此时需要将机器人的姿态调整(示教)到垂直于工作平面的状态,然后记录当前的姿态,作为之后作业的参考标准姿态。不同机器人表示控件姿态的方式不一样,但也无外乎3中:旋转矩阵、欧拉角和四元数。 ABB机器人使用的是四元数(可转欧拉角)作为机器人控件姿态的表示方式。这里主要是记录在不通过示教的方式下,如何定义四元数,使机器人达到垂直于工作平面的姿态。 5轴竖直向下(常用):此时,各轴角度为 [0,0,0,0,9...

Zythonista的博客 1万+

使用 AFL++ 对 IoT 二进制文件进行模糊测试 - 第一部分

American fuzzy lop 是一款面向安全的模糊测试器,它采用一种新型的编译时插桩和遗传算法,可以自动发现干净、有趣的测试用例,从而触发目标二进制文件中新的内部状态。这显著提高了模糊测试代码的功能覆盖率。AFL 的地址是它已经有一段时间没有更新了。虽然 AFL 仍然运行良好,但有一个新项目 AFL++,它是 AFL 的一个分支,包含许多改进和新功能。AFL++ 的地址是,其源代码位于。在本文中,我们将研究如何使用 AFL++ 对 IoT 二进制文件进行模糊测试。

技术超强的网络安全平台 1089

【数据结构】堆的概念、结构、模拟实现以及应用

本篇我们来介绍一下数据结构中的堆。

2402_82757055的博客 2004

Python与PyCharm安装配置教程:从零搭建开发环境

编程入门的第一步是搭建开发环境,而Python解释器与IDE工具的选择常让新手困惑。Python作为解释型语言,负责将代码翻译为机器指令,而PyCharm作为集成开发环境,提供代码编辑、调试与项目管理功能,两者协同工作构成高效开发基础。环境变量PATH的配置是安装过程中的关键环节,正确处理可避免“python不是内部或外部命令”的常见错误。理解pip包管理机制,则能轻松安装第三方库并管理项目依赖。从下载官方安装包到运行第一个Hello World程序,再到利用虚拟环境隔离应用依赖,这套流程适用于Window

benben 685

机械转码日记【3】——《数据结构》堆的实现及堆的应用

堆是什么?如何实现堆排序?以及TopK问题?看完这篇博客你就懂了!

李鑫的博客 1392

超详细!新手必看STM32-DMA配置与实验(串口使用DMA发送数据)

DMA就是:直接存储器访问。DMA传输数据从一个地址空间复制到另一个地址空间,提供在外设和存储器或者存储器和存储器之间的高速数据传输。

qq_1033275663的博客 2万+

深度探索:非线性随机森林(Nonlinear Random Forest,NL-RF)原理及应用

非线性随机森林(NL-RF)旨在通过结合集成方法与高级技术来捕捉和建模数据中的非线性关系,从而改善传统随机森林在处理复杂非线性数据结构时的表现。

qq_51320133的博客 2067

数据结构-堆的实现和应用

数据结构堆,

wdnmdfky的博客 2372

NTC热敏电阻选型快速指南

NTC(Negative Temperature Coefficient Thermistor)负温度系数热敏电阻器,是由锰Mn,镍Ni,铜Cu,一氧化碳Co等烧结而成的氧化物。其电阻值随温度的升高而减小,即具有复温度系数,故被称为负温度系数热敏电阻。本文对热敏电阻的应用场景,结构特点和选型参数进行总结。

fydar的博客 1296

堆的c语言实现以及简单应用

前言:(废话~😢) 嘿嘿,大家好啊,首先,非常感谢您能抽出宝贵时间来看我的文章,虽然你在看这句的时候已经在浪费了...┭┮﹏┭┮ 啊不是,欸嘿(●'◡'●)。 总之,堆是数据结构中我们接触二叉树遇到的第一个比较强劲的对手呢!哼哼<(  ̄^ ̄)( 所以,来和我一起,打败他,从这位身上吸取宝贵的经验吧~~ 一、堆的认知: 既然要打败对手,那么关于它的认知是必不可少的!它是一个完全二叉树,关于二叉树以及树的介绍可以查询相关资料哦~这里我只介绍几种和堆相关的嘻嘻~😛。 注意,这里代码实现的时候.

QiHai的博客 1940

手把手教你学Simulink--人形机器人控制场景实例:基于Simulink的多连杆人形机器人拉格朗日动力学建模仿真

matlab编辑% 连杆长度 (m)% 躯干(髋到CoM)% 大腿% 小腿% 质量 (kg)% 转动惯量(绕质心,简化为杆)matlab编辑% 躯干CoM(假设在髋上方L_body/2处)% 左大腿CoM% 左小腿CoM% (右腿类似,略)本文完成了基于Simulink的多连杆人形机器人拉格朗日动力学建模仿真,实现了:✅ 定义7-DOF平面人形结构✅ 使用Symbolic Math Toolbox自动推导动力学方程✅ 生成。

MHD0815的博客 147

RT-DETR改进策略【卷积层】| CVPR2025 GBConv轻量门控瓶颈卷积 低秩瓶颈降参 + 门控聚焦形态,强效捕捉纤细目标

裂缝形态不规则、纹理纤细,传统卷积参数大、计算冗余,且无法动态聚焦裂缝形态;背景噪声强易干扰特征提取,需要轻量且能自适应聚焦裂缝形态的卷积单元,因此提出轻量门控瓶颈卷积 GBC。

Limiiiing的博客 142

【数据结构】堆(堆的实现 堆向下调整算法 堆的创建 堆的插入 堆的删除 堆的代码实现 堆的应用)

给出一个数组,逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们把它构建成一个堆。删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。建堆和堆删除中都用到了向下调整,因此必须掌握了向下调整。先插入一个数组的尾上,再进行向上调整算法,直到满足堆。开始调整,一直调整到根节点的树,就可以调整成堆。1.将堆顶元素与堆中追后一个元素进行交换。堆是一个完全二叉树:分为小根堆和大根堆。大根堆:任何一个节点的值都>=孩子的值。前提:左右子树必须是一个堆,才能调整。

m0_68800221的博客 565

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

堆的简单实现及其应用

/* * * 堆的特性 * * 1. 堆是一颗二叉树 * 2. 堆的每个节点都比它的子节点要大 * * 堆的常见应用 * * 1. 堆排序 * 2. 优先队列 * * */ /* * * 下面是一个堆的普通实现 * */ class Heap { /* * * 这里用数组来表示一个堆, * +-+-+-+-+-+-+-+ * |0|1|2|...

414

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

堆的底层和实现及相关应用

堆是一种基于树的数据结构,通常用完全二叉树实现。完全二叉树:除了最后一层外,其他层的节点都达到最大,并且最后一层的节点从左到右排列。满二叉树:每一层的节点都被完全填满的二叉树,并且每个非叶子节点都有两个子节点完全二叉树1/ \2 3/ \ /4 5 6满二叉树1/ \2 3/ \ / \4 5 6 7满二叉树也是完全二叉树。

hongcaixia的博客 1239

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【数据结构】堆的实现及应用

简单不先于复杂,而是在复杂之后。

Lixinze__的博客 1290

堆的结构实现与应用

我们只要记住关键的两点:1.堆必须是完全二叉树。2.堆要么是大堆,要么是小堆。

2301_79698419的博客 1203

模拟实现堆+堆的应用

堆数据结构是一种数组对象,它可以被看作一颗完全二叉树的结构(数组是完全二叉树),堆是一种静态结构。 堆分为最大堆和最小堆。 最大堆:每个父结点都大于孩子结点。 最小堆:每个父结点都小于孩子结点。堆的优势:效率高,可以找最大数最小数,增删的时间复杂度为lgN,快 怎么找最后一个叶子结点? 找到最后一个叶子结点(左孩子为空就是叶子结点),由于堆是静态结构,所以我们要通过计算下标的方法找,计算它

zhuohaiyy的博客 482

数据结构——堆的实现与应用

我们知道二叉树有两种存储结构:一种是链式结构,一种是数组结构。由于数组结构的特殊性,它通常被用来存储完全二叉树。而数组结构的完全二叉树中又有一个特殊的数据结构,那就是堆。这一节将介绍堆的实现和堆的应用。...

cainiaochufa2021的博客 1149
上一篇: 链式二叉树的实现
下一篇: 【C++入门】1命名空间、缺省参数与函数重载
Abstract_manner
博客等级 码龄3年 130粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值