【数据结构】详解二叉树之堆

失败只是暂时停止成功,假如我不能,我就一定要;假如我要,我就一定能!💓💓💓

目录

 ✨说在前面

🍋知识点一:树的概念和结构

 • 🌰1.什么是树?

• 🌰2.树的相关概念

• 🌰3.树的表示方法

• 🌰4.树在实践中的运用

🍋知识点二:二叉树的概念和结构 

• 🌰1.什么是二叉树?

• 🌰2.二叉树的性质

• 🌰4.二叉树的存储结构

🍋知识点三:堆 

• 🌰1.什么是堆?

 • 🌰2.堆的基本操作

•🔥堆的初始化

•🔥堆的扩容

•🔥堆的向上调整算法

•🔥堆的插入

•🔥堆的向下调整算法

•🔥堆的删除

•🔥取堆顶数据

•🔥堆的数据个数

•🔥判断堆是否为空

•🔥堆的销毁

• 🌰3.堆的应用

•🔥堆排序

•🔥TOP-K问题

• ✨SumUp结语


 ✨说在前面

亲爱的读者们大家好!💖💖💖,我们又见面了,到现在为止,我们已经学习了很多的数据结构,从最开始的顺序表,到栈和队列。从这篇开始,我们将进入二叉树这一数据结构的学习。不同于之前的数据结构,二叉树的知识比较抽象,需要大家有比较好的想象和思考能力~

今天我们将要学习二叉树中堆的内容,那什么是二叉树,什么是堆,他们用什么来实现,又有什么作用呢?我们今天就解开它神秘的面纱,详细剖析这个新的数据结构吧~

    

  博主主页传送门:愿天垂怜的博客

🍋知识点一:树的概念和结构

 • 🌰1.什么是树?

树是数据结构中的一种,且其属于非线性数据结构结构的一种,我们前文所提到的数据结构多数都是线性的,这也是较为简单的数据结构,而树属于非线性数据结构,也是概念极多的一类。

下面是我们生活中所说的一颗树:

那我们数据结构中的数和现实中的树有什么相似的地方呢?又有什么区别呢?

树的定义:由n(n>=0)个有限结点组成一个具有层次关系的集合。如果n=0,那么它就是一颗空树。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

如图所示,为一颗树:

根结点:根节点没有前驱结点。
除根节点外,其余结点被分成是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。
因此,树是递归定义的。

同时,我们要注意子树不可以相交。

• 🌰2.树的相关概念

节点的度:一个节点含有的子树的个数称为该节点的度;如上图,10的度为2

叶节点(终端节点):度为0的节点称为叶节点;如上图中的5、13...为叶节点

分支节点(非终端节点):度不为0的节点;如上图中的20、15...为分支节点

父节点(双亲节点):若一个节点含有子节点,则称这个节点为其子节点的父节点;如上图,10是5的父节点

子节点(孩子节点):一个节点含有的子树的根节点称为该节点的子节点;如上图,5和20是10的子节点

兄弟节点:具有相同的父节点的节点互称为兄弟节点;如上图5和20、15和30分别互为兄弟节点

树的度:一棵树中,最大的节点的度称为树的度;如上图,数的度为2

节点的层次:从根开始定义起,根为第一层,根的子节点为第二层,以此类推

堂兄弟节点:双亲在同一层的节点互为堂兄弟节点;如上图中的13和28互为堂兄弟节点

节点的祖先:从根到该节点所经分支上的所有节点;如上度,10是所有节点的祖先

子孙:以某节点为根的子树中任一节点都称为该节点的子孙;如上图,所有节点都是10的子孙

森林:由m(m>0)可互不相交的树构成的结合称为森林

  

• 🌰3.树的表示方法

树的结构相对于线性表来说就复杂了许多,要存储表示起来就比较麻烦了,既要保存数据域,也要保存节点与节点之间的关系,实际上数有很多种表示方式,如:双亲表示法,孩子表示法,双亲表示法以及孩子兄弟表示法等。

我们在这里就简单了解一下最常用的孩子兄弟表示法:

我们使用两个指针,一个专门用来指向下一层的子节点,另一个指针用来指向同一层的兄弟节点,这样就比较方便地表示出了树的结构:

具体代码: 

typedef int TDataType;typedef struct TreeNode
{TDataType* val;//节点中的数据域struct TreeNode* leftchild;//第一个孩子节点struct TreeNode* rightbrother;//指向下一个兄弟节点、
}TNode;

  

• 🌰4.树在实践中的运用

树在实践中的应用--表示文件系统的目录树结构。

 

🍋知识点二:二叉树的概念和结构 

• 🌰1.什么是二叉树?

二叉树是n(n>=0)个结点的有限集合,该集合或为空集(称为空二叉树),或由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

二叉树的每个节点最多只能有两个子节点。

下面就是一棵二叉树:

 从上图可以看出:

1.二叉树不存在度大于2的节点

2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

🔥特殊二叉树

1.慢二叉树:一个二叉树,如果它的每一层节点数都达到最大值,则这个二叉树就是慢二叉树。也就是说,如果一个二叉树的层数为K,且总结点数是 2^{K}-1 ,则他就是慢二叉树。

2.完全二叉树:完全二叉树是效率很高的数据机结构,完全二叉树是由满二叉树引出来的。对于深度为K的,有n个节点的二叉树,当且仅当其每一个节点都与深度为K的慢二叉树中编号从1至n的节点一一对应时称之为完全二叉树。

注意:的是慢二叉树是一种特殊的完全二叉树。

  

• 🌰2.二叉树的性质

1.若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^{(i-1)} 个节点.

2.若规定根节点的层数为1,则深度为h的二叉树的最大节点数是 2^{h}-1.

3.对任何一棵二叉树,如果度为0的叶节点个数为n_{0},度为2的分支节点个数为n_{2},则有n_{0} = n_{2} + 1.

4.若规定根节点的层数为1,则具有n个节点的满二叉树的深度 h=log_{2}(n+1) (ps:h=log_{2}(n+1) 是以2为底,n+1的对数).

5.对于具有n个节点的完全二叉树,如果按照从上至下从左至右的数组顺序队所有节点从0开始编号,则队与序号为i的节点有:

🔥若i > 0,i位置的节点的父亲节点:(i - 1) / 2;i = 0,i为根节点编号,无双亲节点

🔥若2i + 1 < n,左孩子序号:2i + 1,若2i + 1 > n,则无左孩子

🔥若2i + 2 < n,右孩子序号:2i + 2,若2i + 2 > n,则无右孩子

  

• 🌰4.二叉树的存储结构

二叉树一般可以使用两种结构存储,一种是顺序结构,一种是链式结构。

1.顺序存储

顺序存储结构就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不完全二叉树会有空间的浪费。而现实中只有才会使用数组来存储。二叉树的顺序存储结构在物理上是一个数组,在逻辑上是一棵二叉树。

2.链式存储

二叉树的链式存储是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个节点由三个域构成,数据域和左右指针域,左右指针分别用来给出该节点左孩子和右孩子所在的链节点的存储地址。链式结构又分为二叉链和三叉链,当前我们学习的一般都是二叉链。

具体代码如下: 

typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{struct BinTreeNode* left; // 指向当前节点左孩子struct BinTreeNode* right; // 指向当前节点右孩子BTDataType data; // 当前节点值域
};
// 三叉链
struct BinaryTreeNode
{struct BinTreeNode* parent; // 指向当前节点的双亲struct BinTreeNode* left; // 指向当前节点左孩子struct BinTreeNode* right; // 指向当前节点右孩子BTDataType data; // 当前节点值域
};

 

🍋知识点三:堆 

• 🌰1.什么是堆?

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

如果有一个关键字集合 K=\left \{ { k_{0},k_{1},k_{2},...,k_{(n-1)}} \right \} ,将它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中并满足 k_{i}\leq k_{2i+1} 且 k_{i}\leq k_{2i+2} (k_{i}\geq k_{2i+1} 且 k_{i}\geq k_{2i+2} )i=0,1,2......,则称之为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

其实说白了就是所有父亲节点比子节点的值大就是大堆,所有父亲节点比子节点的值小就是小堆。

我们知道,我们实际操作的是数组,想象操作的是二叉树。所以我们需要堆这个数据结构的话,需要包含数组、数组的长度和它的空间,我们可以用动态顺序表来实现堆。,具体代码:

typedef int HPDataType;typedef struct Heap
{HPDataType* arr;int size;int capacity;
}HP;

 • 🌰2.堆的基本操作

我们以小堆为例,展示堆的基本操作。

•🔥堆的初始化

堆的初始化和动态顺序表一样,将数组arr初始化为空,再将有效长度和空间都初始化为0.

void HPInit(HP* php)
{assert(php);php->arr = NULL;php->size = php->capacity = 0;
}

 

•🔥堆的扩容

与动态顺序表和栈的扩容相同,我们也已经很熟悉了。由于这个不是堆的基本操作,我们加上static,用来辅助该文件内的其他函数。

static void HPCheckCapacity(HP* php)
{if (php->size == php->capacity){int NewCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* temp = (HPDataType*)realloc(php->arr, NewCapacity * sizeof(HPDataType));if (!temp){perror("realloc operation failed");exit(1);}php->arr = temp;php->capacity = NewCapacity;}
}

 

•🔥堆的向上调整算法

当我们在堆的末尾添加上一个数据后,形成的新的完全二叉树可能不满足堆的性质,这个时候我们需要将最后一个数据进行调整,使得调整之后的完全二叉树仍然是大堆或者小堆。

代码如下:

//交换
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType temp = *p1;*p1 = *p2;*p2 = temp;
}//堆的向上调整算法
void AdjustUp(HPDataType* arr, int child)
{int parent = (child - 1) / 2;while (child > 0){if (arr[parent] < arr[child]){Swap(arr + parent, arr + child);child = parent;parent = (child - 1) / 2;}else{break;}}
}

 

•🔥堆的插入

有了向上调整算法的基础,对于堆的插入操作就很简单了。堆的插入,就是在堆的末尾,也就是数组的末尾插入新的节点,再将这个节点向上调整,使之调整后仍然是之前的大堆或小堆。具体代码如下:

void HPPush(HP* php, HPDataType x)
{assert(php);HPCheckCapacity(php);php->arr[php->size++] = x;AdjustUp(php->arr, php->size - 1);
}

•🔥堆的向下调整算法

当我们需要删除堆顶的数据时,一般需要将堆顶的数据调整到堆的末尾,也就是数组的末尾,让数组的size--就可以了。将堆顶数据调整到堆的末尾,需要用到堆的向下调整算法;或者是根节点换了另外一个值过来,那也不一定满足堆的性质,需要将这个值调整到合适的位置。

具体代码如下:

//交换
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType temp = *p1;*p1 = *p2;*p2 = temp;
}//堆的向下调整算法
void AdjustDown(HPDataType* arr, int n, int parent)
{int child = 2 * parent + 1;while (child < n){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}if (arr[parent] < arr[child]){Swap(arr + parent, arr + child);parent = child;child = 2 * parent + 1;}else{break;}}
}

 

•🔥堆的删除

那么我们理解了堆的向下调整算法,对于堆的删除操作就很简单了。堆的删除就是将堆中根结点和尾节点进行交换,再利用向下调整算法使得调整后仍然是原来的大堆或小堆,但是size减小1。具体代码如下:

void HPPop(HP* php)
{assert(php && php->size);Swap(php->arr, php->arr + php->size - 1);php->size--;AdjustDown(php->arr, php->size, 0);
}

 

•🔥取堆顶数据

不论是大堆还是小堆,堆顶的数据总是在数组的第一个位置。所以我们返回arr[0]就可以了,代码如下:

HPDataType HPTop(HP* php)
{assert(php && php->size);return php->arr[0];
}

 

•🔥堆的数据个数

我们实际上操作的是数组,并且以数组(动态顺序表)的形式实现堆,所以堆的数据个数就是有效数据个数size。

int HPSize(HP* php)
{assert(php);return php->size;
}

 

•🔥判断堆是否为空

和之前栈的判空基本相同,就是去判断有效数据个数size是否为0。我们可以用布尔类型。

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

 

•🔥堆的销毁

和动态顺序表销毁的方式相同。

void HPDestroy(HP* php)
{assert(php);free(php->arr);php->arr = NULL;php->size = php->capacity = 0;
}

  

• 🌰3.堆的应用

•🔥堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆排序总共分为两个步骤:

1.建堆

升序:建大堆

降序:建小堆

2.利用堆删除思想来进行排序。

我们以升序排列为例,排列一组数据:16,14,10,8,7,9,3,2,4,1。我们实际上操作的是数组,想象的是大堆。

接下来,我们将堆顶(最大的数)和尾(最小的数)交换位置,然后重新调整,得到的新的堆重复刚才的操作即可:
 

注意:上述20应该改为16 。

具体代码:

void HeapSort(int* arr, int length)
{//向下调整建堆O(N)for (int i = (length - 2) / 2; i >= 0; i--){AdjustDown(arr, length, i);}while (length - 1)//O(NlogN){Swap(arr, arr + length - 1);AdjustDown(arr, length - 1, 0);length--;}
}

在代码中,我们能看到向下调整建堆的过程。也就是说,我们要将数组中存放的数据想象成堆,那么建堆的过程,我们用向下调整建堆,这个过程的复杂度是O(N),具体推导过程如下:

 所以建堆过程的时间复杂度为 O(N),而后面while循环的时间复杂度为 O(NlogN),所以堆排序的时间复杂度为 Ο(NlogN)。

 

•🔥TOP-K问题

有了堆排序的基础,我们可以很轻松地解决TOP-K问题。

TOP-K问题:即求数据中前K个最大(或最小)的元素,一般情况下数据量比较大。

比如:专业前10,名、世界500强、富豪榜、游戏中前100名的活跃玩家等。

对于Top-K问题,能想到的最简单直接的方法就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

1.用数据集合中前K个元素来建堆

前k个最大的元素,则建小堆

前k个最小的元素,则建大堆

2.用剩余的N-K个元素一次与堆顶元素来比较,不满足则替换堆顶元素

将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

举例:将data.txt文件中的n个随机数中找到最大的前k个。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <stdbool.h>//创造数据
void CreateData()
{int n = 100000;srand((unsigned int)time(NULL));FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen operation failed");exit(1);}for (int i = 0; i < n; i++){int x = (rand() + i) % 1000000;fprintf(pf, "%d\n", x);}fclose(pf);pf = NULL;
}//堆排序
void HeapSort(int* arr, int length)
{assert(arr);for (int i = (length - 2) / 2; i >= 0 ; i--){AdjustDown(arr, length, i);}while (length - 1){Swap(arr, arr + length - 1);AdjustDown(arr, length - 1, 0);length--;}
}void TestHeap()
{//创建k个数的小堆int k = 0;printf("请输入k值->");scanf("%d", &k);int* k_min_heap = (int*)malloc(k * sizeof(int));if (k_min_heap == NULL){perror("malloc operation failed");exit(1);}FILE* pfout = fopen("data.txt", "r");if (pfout == NULL){perror("fopen operation failed");exit(1);}//读取文件前k个数for (int i = 0; i < k; i++){fscanf(pfout, "%d", &k_min_heap[i]);}for (int i = (k - 2) / 2; i >= 0; i--){AdjustDown(k_min_heap, k, i);}//读取剩下的n-k个数int receive = 0;while ((fscanf(pfout, "%d", &receive)) != EOF){if (receive > k_min_heap[0]){k_min_heap[0] = receive;AdjustDown(k_min_heap, k, 0);}}HeapSort(k_min_heap, k);//遍历后的大堆即为Top—K数printf("最大的前%d个数为:", k);for (int i = 0; i < k; i++){printf("%d ", k_min_heap[i]);}printf("\n");
}int main()
{CreateData();TestHeap();return 0;
}

• ✨SumUp结语

到这里本篇文章的内容就结束了,数这个数据结构比我们以往的数据结构更加抽象,相信大家看完本篇文章已经发现堆的实现已经比较复杂了,甚至涉及到了错位相减的计算方法。后面内容的难度相对于堆只增不减,希望大家可以好好复习今天的内容,自己尝试写代码~

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】学分制系统GetTimeTableData SQL注入

0x01 产品简介 学分制系统由上海鹏达计算机系统开发有限公司研发&#xff0c;是基于对职业教育特点和需求的深入理解&#xff0c;结合教育部相关文件精神&#xff0c;并广泛吸纳专家、学者意见而开发的一款综合性管理系统。系统采用模块化的设计方法&#xff0c;方便学校根据自…

新奥集团校招面试经验分享、测评笔试题型分析

一、走进新奥集团 新奥集团成立于1989年&#xff0c;总部位于河北廊坊&#xff0c;是中国领先的清洁能源企业集团。业务涵盖城市燃气、能源化工、环保科技等多个领域&#xff0c;致力于构建现代能源体系&#xff0c;提升生活品质。 二、新奥集团校招面试经验分享 新奥集团的…

小程序驾校预约系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学员管理&#xff0c;教练管理&#xff0c;驾校信息管理&#xff0c;驾校车辆管理&#xff0c;教练预约管理&#xff0c;考试信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;驾校信息&a…

ROS2创建自定义接口

ROS2提供了四种通信方式&#xff1a; 话题-Topics 服务-Services 动作-Action 参数-Parameters 查看系统自定义接口命令 使用ros2 interface package sensor_msgs命令可以查看某一个接口包下所有的接口 除了参数之外&#xff0c;话题、服务和动作(Action)都支持自定义接口&am…

【智能算法】决策树算法

目录 一、基本概念 二、工作原理 三、决策树算法优点和缺点 3.1 决策树算法优点 3.2 决策树算法缺点 四、常见的决策树算法及matlab代码实现 4.1 ID3 4.1.1 定义 4.1.2 matlab代码实现 4.2 C4.5 4.2.1 定义 4.2.2 matlab代码实现 4.3 CART 4.3.1 定义 4.3.2 mat…

android轮播图入门1——简单无限自动轮播图

目标 目标是实现一个简单的轮播图&#xff0c;特征如下&#xff1a; 只展示本地图片可以无限轮播&#xff0c;在第一帧时也可以向前轮播可以自动轮播 code 先上代码&#xff0c;需要事先准备几张本地图片当素材 MainActivity: package com.example.loopapplication;import…

【数据结构】——链表经典OJ(leetcode)

文章目录 一、 相交链表二、 反转链表三、 回文链表四、 环形链表五、 环形链表 II六、 合并两个有序链表七、 两数相加八、 删除链表的倒数第N个节点九、 随机链表的复制 一、 相交链表 双指针法 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListN…

day02-Spark集群及参数

一、Spark运行环境变量问题(了解) 1-pycharm远程开发运行时&#xff0c;执行的是服务器的代码 2-通过本地传递指令到远程服务器运行代码时&#xff0c;会加载对应环境变量数据&#xff0c;加载环境变量文件是用户目录下的.bashrc文件 在/etc/bashrc 1-1 在代码中添加 使用os模块…

Python 算法交易实验74 QTV200第二步(改): 数据清洗并写入Mongo

说明 之前第二步是打算进入Clickhouse的&#xff0c;实测下来有一些bug 可以看到有一些分钟数据重复了。简单分析原因&#xff1a; 1 起异步任务时&#xff0c;还是会有两个任务重复的问题&#xff0c;这个在同步情况下是不会出现的2 数据库没有upsert模式。clickhouse是最近…

mysql GROUP_CONCAT函数详解

文章目录 概要使用技巧1. 建表、插入数据2.以id分组&#xff0c;把age字段的值拼成一行&#xff0c;逗号分隔(默认)3.以id分组&#xff0c;把age字段的值拼成 一行&#xff0c;分号分隔4.以id分组&#xff0c;把去冗余的age字段的值打印在一行5.以id分组&#xff0c;把age字段的…

算法:链表题目练习

目录 链表的技巧和操作总结 常用技巧&#xff1a; 链表中的常用操作 题目一&#xff1a;反转一个单链表 题目二&#xff1a;链表的中间结点 题目三&#xff1a;返回倒数第k个结点 题目四&#xff1a;合并两个有序链表 题目五&#xff1a;移除链表元素 题目六&#xff…

利用LLM本身训练SoTA embedding模型

今天分享一篇Microsoft公司的一篇文章&#xff0c;Title: Improving Text Embeddings with Large Language Models&#xff1a;使用大语言模型改善文本嵌入。 这篇文章探索了直接利用LLM来做embedding模型&#xff0c;其只需要利用合成数据和少于1000次的训练步骤就能获得高质…

语言模型:文本表征词嵌入技术调研

1 文本表征 文本表征是自然语言处理中的关键部分&#xff0c;尤其在当前大模型快速发展的背景下。由于大模型存在知识有限、处理文本长度有限、保密要求和大模型幻觉等问题&#xff0c;结合外部数据显得尤为重要。 为了便于存储和检索&#xff0c;除了保存纯文本外&#xff0…

Debug 调试代码

我们使用 debug 的目的, 认为就是查看代码的执行过程的。 步骤&#xff1a; 1. 打断点 断点的意义是, debug 运⾏的时候, 代码会在断点处停下来不执行如果是想要查看代码的执行过程, 建议将断点放在第⼀行在代码 和 行号之间 点击,出现的红色圆点 就是断点, 再次点击可以取消 …

Webpack: 构建微前端应用

Module Federation 通常译作“模块联邦”&#xff0c;是 Webpack 5 新引入的一种远程模块动态加载、运行技术。MF 允许我们将原本单个巨大应用按我们理想的方式拆分成多个体积更小、职责更内聚的小应用形式&#xff0c;理想情况下各个应用能够实现独立部署、独立开发(不同应用甚…

apipost的安装和测试添加接口能否正常使用

1.进入官网&#xff0c;点击免费使用&#xff08;我是windows 64位&#xff0c;选合适自己的配置&#xff09; 2.开始安装 选仅为我安装——下一步 选择自己的安装目录——点安装 等待 运行——完成 3.apipost一些基本操作——实现添加内容 &#xff08;1&#xff09;新建接口…

《人人都是产品经理》:项目一图流

《人人都是产品经理》&#xff1a;项目一图流 项目一图流 项目一图流

FreeSWITCH 1.10.10 简单图形化界面22-JsSIP的demo测试并记录坑

FreeSWITCH 1.10.10 简单图形化界面22-JsSIP的demo测试 00 FreeSWITCH GUI界面预览01、安装FreeSWITCH GUI先看使用手册02. 使用手册在这里0、设置FreeSWITCH账号1、jssip的demo网站2、设置jssip账号并登录3、整理坑3.1 掉线问题3.11 解决3.2 呼叫问题13.21 解决13.3 呼叫问题2…

PAE:从潮流报告中提炼有效产品属性

本文将介绍PAE&#xff0c;一种用于包含 PDF格式的文本和图像的产品属性提取算法。目前大部分的方法侧重于从标题或产品描述中提取属性&#xff0c;或利用现有产品图像中的视觉信息。与之前的工作相比&#xff0c;PAE从潮流趋势报告的PDF文件中提取属性&#xff0c;提取的属性包…

spl实现循环计算

需求 需要对一批数据进行价格计算 这里面的一部分单价来自于历史记录&#xff0c;但是另外一部分的单价&#xff0c;需要边计算边存储 数据库结构 CREATE TABLE tbl_mix_trace_price (lot_id_out varchar(255) DEFAULT NULL COMMENT 产出,lot_id_in varchar(255) DEFAULT NULL…