堆的介绍,实现(c语言实现)

目录

堆的概念

堆的性质:

堆的分类 

父子结点的下标关系

堆的向下调整算法

​编辑小堆 

大堆

 建堆

堆的向上调整算法

小堆

 大堆

堆的基本操作

定义堆

初始化堆

 销毁堆

打印堆

堆的插入

堆的删除

大堆(Max Heap)的向下调整算法思路:

小堆(Min Heap)的向下调整算法思路:

关键点解释:

获取堆的数据个数

堆的判空


堆的概念

如果有一个关键码的集合K = { k1,k2 ,k3 ,…, },把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:i = 0,1, 2…,则称为小堆(或大堆)。

在数据结构中,堆(Heap)是一种特殊的树形数据结构,通常被实现为完全二叉树或近似完全二叉树。堆的一个重要特性是它满足堆属性,即每个节点的值都大于或等于(在最大堆中)或小于或等于(在最小堆中)其子节点的值。

堆在计算机科学中有广泛的应用,尤其是在实现优先队列和堆排序算法中。优先队列是一种数据结构,其中元素的优先级决定了它们的出队顺序。堆可以作为一种高效的优先队列实现方式,因为堆顶元素总是优先级最高(最大或最小)的元素。堆排序算法则利用堆的性质,通过构建最大堆或最小堆,并反复取出堆顶元素来实现排序。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的性质:

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

堆的分类 

堆主要分为两种类型:最大堆(Max Heap)和最小堆(Min Heap)。在最大堆中,父节点的值总是大于或等于其子节点的值,因此堆顶元素是整个堆中的最大值。相反,在最小堆中,父节点的值总是小于或等于其子节点的值,堆顶元素是整个堆中的最小值。 

堆通常使用数组来实现,数组中的每个元素对应堆中的一个节点。由于堆是完全二叉树,所以可以使用数组的下标关系来模拟树中父节点和子节点之间的关系。这种实现方式使得堆在插入、删除和查找最大(或最小)元素等操作中具有高效的性能。

 

父子结点的下标关系

在堆的数据结构中,我们通常将数组中的每个元素视为一个结点,这些结点按照完全二叉树的顺序存储在数组中。每个结点都有一个唯一的下标,通过下标关系,我们可以确定任意结点的父结点和子结点的位置。

对于给定下标 i 的结点,其父结点、左子结点和右子结点的下标可以通过以下关系式计算:

  • 下标i元素的父结点下标:(i - 1) / 2(使用整数除法)
  • 下标i元素的左子结点下标:2 * i + 1
  • 下标i元素的右子结点下标:2 * i + 2

这些关系式基于完全二叉树的性质。在完全二叉树中,除了最后一层,其他层的结点是满的,且最后一层的结点都靠左对齐。因此,对于任意结点,其左子结点的下标是其下标的两倍加一,右子结点的下标是其下标的两倍加二,而父结点的下标则是通过将其下标减一后除以二(整数除法)得到。

通过这些下标关系,我们可以方便地在数组中进行堆的操作,如插入、删除、堆化等。例如,在插入新元素时,我们可以将其放在数组的末尾,并通过与其父结点比较和交换(如果需要)来维护堆的性质。同样地,在删除堆顶元素时,我们可以将数组的最后一个元素移动到堆顶,并通过与其子结点比较和交换来重新调整堆。

需要注意的是,当使用这些下标关系时,我们需要确保下标不会超出数组的范围。例如,根结点的下标为 0,它没有父结点。对于任意结点,我们需要检查其左子结点和右子结点的下标是否超出了数组的长度,以避免访问不存在的元素。

通过使用结点和下标关系,我们可以高效地实现堆的数据结构,并利用其特性进行各种操作,如快速找到最大(或最小)元素、插入新元素、删除元素等。

堆的向下调整算法

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整 成一个小堆。

但是,使用向下调整算法需要满足一个前提:

  1.  若想将其调整为小堆,那么根结点的左右子树必须都为小堆。
  2.  若想将其调整为大堆,那么根结点的左右子树必须都为大堆。

小堆 

向下调整算法的基本思想(以建小堆为例):

  1. 从根结点处开始,选出左右孩子中值较小的孩子。
  2. 让小的孩子与其父亲进行比较。

       (1) 若小的孩子比父亲还小,则该孩子与其父亲的位置进行交换。并将原来小的孩子的位置                   当成父亲继续向下进行调整,直到调整到叶子结点为止。
        (2)若小的孩子比父亲大,则不需处理了,调整完成,整个树已经是小堆了。

//交换函数
void Swap(int* x, int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

//堆的向下调整(小堆)
void AdjustDown(int* a, int n, int parent)
{
	//child记录左右孩子中值较小的孩子的下标
	int child = 2 * parent + 1;//先默认其左孩子的值较小
	while (child < n)
	{
		if (child + 1 < n&&a[child + 1] < a[child])//右孩子存在并且右孩子比左孩子还小
		{
			child++;//较小的孩子改为右孩子
		}
		if (a[child] < a[parent])//左右孩子中较小孩子的值比父结点还小
		{
			//将父结点与较小的子结点交换
			Swap(&a[child], &a[parent]);
			//继续向下进行调整
			parent = child;
			child = 2 * parent + 1;
		}
		else//已成堆
		{
			break;
		}
	}
}

大堆

向下调整算法的基本思想(以建大堆为例)如下:

  1. 从根结点处开始,选出左右孩子中值较大的孩子。

  2. 让较大的孩子与其父亲进行比较。

    若较大的孩子比父亲还大,则该孩子与其父亲的位置进行交换。并将原来较大的孩子的位置当成父亲继续向下进行调整,直到调整到叶子结点为止。

    若较大的孩子比父亲小或者没有孩子(即已经是叶子结点),则不需处理了,调整完成,整个树已经是大堆了。

//交换函数
void Swap(int* x, int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

//堆的向下调整(大堆)  
void AdjustDown(HPDataType* a, int n, int parent)  
{  
    int child = parent * 2 + 1; // 计算左子节点的索引  
  
    // 当 child 索引在数组范围内时执行循环  
    while (child < n)  
    {  
        // 如果右子节点存在且大于左子节点  
        if (child + 1 < n && a[child+1] > a[child])  
        {  
            ++child; // 更新 child 为右子节点的索引  
        }  
  
        // 如果 child 节点(现在是左右子节点中较大的一个)大于 parent 节点  
        if (a[child] > a[parent])  
        {  
            Swap(&a[child], &a[parent]); // 交换 parent 和 child 的值  
            parent = child; // 更新 parent 为刚刚交换过的 child 的索引  
            child = parent * 2 + 1; // 重新计算左子节点的索引  
        }  
        else  
        {  
            break; // child 节点不大于 parent 节点,无需继续调整,退出循环  
        }  
    }  
}

 使用堆的向下调整算法,最坏的情况下(即一直需要交换结点),需要循环的次数为:h - 1次(h为树的高度)。而h=log_{2}(n+1)(N为树的总结点数)。所以堆的向下调整算法的时间复杂度为:O(logN) 。 

 建堆

 上面说到,使用堆的向下调整算法需要满足其根结点的左右子树均为大堆或是小堆才行,那么如何才能将一个任意树调整为堆呢?

答案很简单,我们只需要从倒数第一个非叶子结点开始,从后往前,按下标,依次作为根去向下调整即可。

代码

	//建堆
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(php->a, php->size, i);
	}

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

 所以T(n)=O(N)

总结一下:
 堆的向下调整算法的时间复杂度:T(n)=O(logN)。
 建堆的时间复杂度:T(n)=O(N)。

堆的向上调整算法

当我们在一个堆的末尾插入一个数据后,需要对堆进行调整,使其仍然是一个堆,这时需要用到堆的向上调整算法。

小堆

向上调整算法的基本思想(以建小堆为例):

  1. 将目标结点与其父结点比较。
  2. 若目标结点的值比其父结点的值小,则交换目标结点与其父结点的位置,并将原目标结点的父 结点当作新的目标结点继续进行向上调整。
  3. 若目标结点的值比其父结点的值大,则停止向上调整,此时该树已经是小堆了。

//交换函数
void Swap(HPDataType* x, HPDataType* y)
{
	HPDataType tmp = *x;
	*x = *y;
	*y = 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 = (child - 1) / 2;
		}
		else//已成堆
		{
			break;
		}
	}
}

 大堆

向上调整算法的基本思想(以建大堆为例)如下:

  1. 将目标结点与其父结点比较。
  2. 若目标结点的值大于其父结点的值,则交换目标结点与其父结点的位置,并将原目标结点的父结点当作新的目标结点继续进行向上调整。
  3. 若目标结点的值不大于其父结点的值,则停止向上调整,此时该树已经是大堆了。
void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType x = *p1;
	*p1 = *p2;
	*p2 = x;
}

// 除了child这个位置,前面数据构成堆
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while(child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

堆的基本操作

定义堆

typedef int HPDataType;//堆中存储数据的类型

typedef struct Heap
{
	HPDataType* a;//用于存储数据的数组
	int size;//记录堆中已有元素个数
	int capacity;//记录堆的容量
}HP;

初始化堆

然后我们需要一个初始化函数,对刚创建的堆进行初始化,注意在初始化期间要将传入数据建堆。

//初始化堆
void HeapInit(HP* php, HPDataType* a, int n)
{
	assert(php);

	HPDataType* tmp = (HPDataType*)malloc(sizeof(HPDataType)*n);//申请一个堆结构
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	php->a = tmp;
	memcpy(php->a, a, sizeof(HPDataType)*n);//拷贝数据到堆中
	php->size = n;
	php->capacity = n;
	int i = 0;
	//建堆
	for (i = (php->size - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(php->a, php->size, i);
	}
}

当然还有简化的版本

void HeapInit(HP* php)
{
	assert(php);

	php->a = (HPDataType*)malloc(sizeof(HPDataType)*4);
	if (php->a == NULL)
	{
		perror("malloc fail");
		return;
	}

	php->size = 0;
	php->capacity = 4;
}

 销毁堆

 为了避免内存泄漏,使用完动态开辟的内存空间后都要及时释放该空间,所以,一个用于释放内存空间的函数是必不可少的。

//销毁堆
void HeapDestroy(HP* php)
{
	assert(php);

	free(php->a);//释放动态开辟的数组
	php->a = NULL;//及时置空
	php->size = 0;//元素个数置0
	php->capacity = 0;//容量置0
}

打印堆

 打印堆中的数据,这里用了两种打印格式。第一种打印格式是按照堆的物理结构进行打印,即打印为一排连续的数字。第二种打印格式是按照堆的逻辑结构进行打印,即打印成树形结构。

//求结点数为n的二叉树的深度
int depth(int n)
{
	assert(n >= 0);

	if (n>0)
	{
		int m = 2;
		int hight = 1;
		while (m < n + 1)
		{
			m *= 2;
			hight++;
		}
		return hight;
	}
	else
	{
		return 0;
	}
}

//打印堆
void HeapPrint(HP* php)
{
	assert(php);
	//按照物理结构进行打印
	int i = 0;
	for (i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
	}
	printf("\n");
	//按照树形结构进行打印
	int h = depth(php->size);
	int N = (int)pow(2, h) - 1;//与该二叉树深度相同的满二叉树的结点总数
	int space = N - 1;//记录每一行前面的空格数
	int row = 1;//当前打印的行数
	int pos = 0;//待打印数据的下标
	while (1)
	{
		//打印前面的空格
		int i = 0;
		for (i = 0; i < space; i++)
		{
			printf(" ");
		}
		//打印数据和间距
		int count = (int)pow(2, row - 1);//每一行的数字个数
		while (count--)//打印一行
		{
			printf("%02d", php->a[pos++]);//打印数据
			if (pos >= php->size)//数据打印完毕
			{
				printf("\n");
				return;
			}
			int distance = (space + 1) * 2;//两个数之间的空格数
			while (distance--)//打印两个数之间的空格
			{
				printf(" ");
			}
		}
		printf("\n");
		row++;
		space = space / 2 - 1;
	}
}

堆的插入

 数据插入时是插入到数组的末尾,即树形结构的最后一层的最后一个结点,所以插入数据后我们需要运用堆的向上调整算法对堆进行调整,使其在插入数据后仍然保持堆的结构。

void HeapPush(HP* php, HPDataType x)
{
	assert(php);

	if (php->size == php->capacity)
	{
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity *= 2;
	}

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

	AdjustUp(php->a, php->size - 1);
}

 这个插入的效果完全取决于AdjustUp函数是给大堆设计的还是小堆!!

堆的删除

的向下调整算法思路主要涉及到在删除堆顶元素(最大或最小元素)后,从堆的最后一个元素开始,将其放到堆顶,并通过一系列的交换操作来重新维护堆的性质。这个算法在堆排序和优先队列等应用中非常关键。

大堆(Max Heap)的向下调整算法思路:

  1. 准备阶段
    • 假设堆中当前有 n 个元素,删除堆顶元素后,将最后一个元素(第 n 个元素)移动到堆顶位置。
    • 初始化当前节点 k 为堆顶节点(索引为 0 或 1,取决于实现)。
  2. 调整过程
    • 获取当前节点 k 的左右子节点的索引。
    • 比较当前节点 k 的值与左右子节点的值,找到三者中的最大值。
    • 如果最大值不是当前节点 k,则将其与最大值所在位置的节点交换。
    • 更新 k 为交换后的最大值所在位置的节点索引。
    • 重复上述步骤,直到 k 没有子节点或者 k 的值不小于其子节点的值,此时堆的性质得以恢复。

小堆(Min Heap)的向下调整算法思路:

  1. 准备阶段
    • 与大堆类似,删除堆顶元素后,将最后一个元素移动到堆顶位置。
    • 初始化当前节点 k 为堆顶节点。
  2. 调整过程
    • 获取当前节点 k 的左右子节点的索引。
    • 比较当前节点 k 的值与左右子节点的值,找到三者中的最小值。
    • 如果最小值不是当前节点 k,则将其与最小值所在位置的节点交换。
    • 更新 k 为交换后的最小值所在位置的节点索引。
    • 重复上述步骤,直到 k 没有子节点或者 k 的值不大于其子节点的值,此时堆的性质得以恢复。

关键点解释:

  • 子节点索引:对于数组实现的堆,可以通过 (k * 2 + 1) 和 (k * 2 + 2) 来获取当前节点 k 的左子节点和右子节点的索引(假设数组下标从 0 开始)。
  • 比较与交换:根据堆的性质(大堆或小堆),比较当前节点与其子节点的值,并根据需要进行交换,以保证堆的性质得以维持。
  • 终止条件:当当前节点 k 没有子节点(即 k 的索引超过了数组长度的一半减一),或者当前节点的值已经满足堆的性质(对于大堆是不小于子节点,对于小堆是不大于子节点)时,算法终止。

通过这种向下调整算法,可以在删除堆顶元素后快速恢复堆的性质,使得堆能够继续作为有效的数据结构进行后续操作。

//堆的删除
void HeapPop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));

	Swap(&php->a[0], &php->a[php->size - 1]);//交换堆顶和最后一个结点的位置
	php->size--;//删除最后一个结点(也就是删除原来堆顶的元素)
	AdjustDown(php->a, php->size, 0);//向下调整
}

获取堆的数据个数

获取堆的数据个数,即返回堆结构体中的size变量。

//获取堆中数据个数
int HeapSize(HP* php)
{
	assert(php);

	return php->size;//返回堆中数据个数
}

堆的判空

堆的判空,即判断堆结构体中的size变量是否为0。

//堆的判空
bool HeapEmpty(HP* php)
{
	assert(php);

	return php->size == 0;//判断堆中数据是否为0
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/580363.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

白酒:香型创新在白酒市场竞争中的优势与策略

在香型创新方面展现出明显的市场竞争优势&#xff0c;香型创新不仅满足了消费者对口味多样化的需求&#xff0c;还为酒厂带来了差异化竞争优势。在白酒市场竞争中&#xff0c;实施进一步的香型创新策略对于提升品牌曝光度和市场份额至关重要。 首先&#xff0c;香型创新能够满足…

三篇多模态大模型进展综述

Modality Bridging 综述 多模态大型语言模型&#xff08;MLLM&#xff09;可实现基于图像撰写故事和无 OCR 的数学推理&#xff0c;在传统方法中很少见&#xff0c;这表明了通向通用人工智能的潜在路径。 通常人们会在 pair 数据上进行大规模&#xff08;相对于 instruction t…

【千帆平台】AppBuilder工作流编排新功能体验之创建自定义组件

欢迎来到《小5讲堂》 这是《千帆平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言工作流编排组件 创建组件组件界面组件信息 组件画布操作节点…

探索项目管理系统:解析五大功能,洞悉项目成功的关键

项目管理新手往往喜欢埋头苦干&#xff0c;殊不知优秀的项目经理已经熟练运用项目管理系统&#xff0c;让项目规划条理清晰。项目管理系统具备的功能&#xff0c;好用的项目管理系统都有这5大功能。分别是项目WBS分解、项目图表和报表、工时管理、团队协作、任务流程自动化。 一…

(学习日记)2024.04.28:UCOSIII第五十二节:User文件夹函数概览(uC-LIB文件夹)第二部分

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

【中级软件设计师】上午题12-软件工程(1):软件工程模型、敏捷方法、软件需求、系统设计

上午题12-软件工程&#xff08;1&#xff09; 1 软件过程1.1 CMM 能力成熟度模型1.1 CMMI (建议直接看思维导图&#xff09; 2 软件过程模型2.1 瀑布模型2.2 增量模型2.3 演化模型2.3.1 原型模型2.3.2 螺旋模型 2.5 喷泉模型 3 统一过程&#xff08;UP&#xff09;模型4 敏捷方…

YOKOGAWA横河手操器维修hart通讯器YHC5150X-01

横河手操器设置注意事项&#xff1a;内藏指示计显示选择与单位设置 有如下 5 种显示模式及单位设置百分比显示、用户设置显示、用户设置和百分比交替显示、输入压力显示、输入压力和百分比交替显示。即应用在当没有输入时操作要求输出为20mA引压方向设置右/左侧高压&#xff0c…

CAS原理及其API原子类

目录 1.CAS及使用 1.1. CAS概念 1.2.原子类的使用 1.3.CAS使用自旋锁 2.CAS的ABA问题 2.1.问题介绍 2.2.ABA问题解决方式 1.CAS及使用 1.1. CAS概念 &#xff08;1&#xff09;CAS&#xff0c;其实是一种操作的简称&#xff0c;全称为&#xff1a;Compare and swap。 …

HNU-数据库系统-甘晴void学习感悟

前言 过程坎坷&#xff0c;终局满意。 感觉是学懂了知识&#xff0c;并且拿到了分数这样的学科。 【先把这个位置占下来&#xff0c;之后有时间再补充】 教材如下&#xff1a; 总领 有点忘记了&#xff0c;可参考当时记录的笔记&#xff1a; 数据库系统-甘晴void学习笔记-…

【三】Spring Cloud Ribbon 实战

Spring Cloud Ribbon 实战 概述 一直在构思写一个spring cloud系列文章&#xff0c;一方面是对自己实践经验进行一次完整的梳理&#xff0c;另一方面也是希望能够给初学者一些借鉴&#xff0c;让初学者少走些弯路&#xff0c;看到本系列博客就能够很好的把微服务系列组件用好。…

使用QTcpSocket

(1)客户端每隔10ms向服务器发送一次数字字符串&#xff0c;从0开始。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTcpSocket> #include <QLabel> #include <QTimer> namespace Ui { class MainWindow; }class Mai…

MAVEN的安装与配置

MAVEN的安装与配置 1 简介 1.1 什么是MAVEN? Maven是一个项目构建及管理工具&#xff0c;开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置&#xff0c; Maven 使用了一个标准的目录结构在不同开发工具中也能实现项目结构的统一。Maven提供了清理&#xff0c;编…

【Vue】组件化编程

定义 实现应用中局部功能代码和资源的集合 为什么要用组件化编程? 传统方式编写:依赖关系混乱,不好维护,且代码复用率不高 模块化编写:只关注解决js,复用js,简化js的编写与效率 组件方式编写:好维护、复用率更高、提高运行效率 在组件出现之前,我们开发基本都是用htm…

【综述】DSP处理器芯片

文章目录 TI DSP C2000系列 TMS320F28003X 典型应用 开发工具链 参考资料 TI DSP TI C2000系列 控制领域 TI C5000系列 通信领域 TI C6000系列 图像领域 C2000系列 第三代集成了C28浮点DSP内核&#xff0c;采用了65nm工艺&#xff08;上一代180nm&#xff09; 第四代正在…

PyCharm 无法运行的解决方案

问题&#xff1a; PyCharm 无法运行&#xff0c;该怎么办&#xff1f; 解决方案&#xff1a; 1. 检查 Python 解释器 确保已为 PyCharm 配置正确的 Python 解释器。打开 PyCharm&#xff0c;转到“文件”>“设置”>“项目”>“Python 解释器”。选择所需的 Python …

怎么在海外平台买东西?Nike海淘攻略

不管在那个海外平台买东西首先要进入官网&#xff0c;最好注册一个gmail账号&#xff0c;这样使用范围比较宽广&#xff0c;在对应平台进行注册账号&#xff0c;比如亚马逊、ebay、Etsy等等 一、Nike海淘攻略 1、然后如果已经会员的话直接输入账号密码登录&#xff0c;如果不…

AI大模型探索之路-训练篇3:大语言模型全景解读

文章目录 前言一、语言模型发展历程1. 第一阶段&#xff1a;统计语言模型&#xff08;Statistical Language Model, SLM&#xff09;2. 第二阶段&#xff1a;神经语言模型&#xff08;Neural Language Model, NLM&#xff09;3. 第三阶段&#xff1a;预训练语言模型&#xff08…

顺通拖鞋ERP企业销售管理系统:驱动销售业绩飙升的利器

顺通企业销售管理系统通过集成客户信息、销售流程、数据分析等功能&#xff0c;帮助企业全面提升销售效率和业绩&#xff0c;成为驱动销售业绩飙升的利器。此外&#xff0c;系统还支持销售流程的可视化展示&#xff0c;使销售人员能够清晰地了解销售进展&#xff0c;及时调整销…

短视频账号矩阵系统===4年技术源头打磨

短视频矩阵系统技术源头打磨需要从多个方面入手&#xff0c;以下是一些建议&#xff1a; 1. 基础技术研发&#xff1a;不断投入资金和人力进行基础技术研发&#xff0c;包括但不限于视频处理、人工智能、大数据等技术&#xff0c;以提高短视频矩阵系统的性能和稳定性。 2. 优化…

JAVA面试八股文之JVM

JVM JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;你能详细说一下 JVM 运行时数据区吗&#xff1f;详细介绍一下程序计数器的作用&#xff1f;你能给我详细的介绍Java堆吗?什么是虚拟机栈&#xff1f;栈内存溢出情况&#xff1f;堆栈的区别是什么吗&#xff1f;解…
最新文章