C/C++ 数据结构与算法【哈夫曼树】 哈夫曼树详细解析【日常学习,考研必备】带图+详细代码
哈夫曼树(最优二叉树)
1)基础概念
**路径:**从树中一个结点到另一个结点之间的分支构成这两个结点间的路径。
**结点的路径长度:**两结点间路径上的分支数。
**树的路径长度:**从树根到每一个结点的路径长度之和。记作:TL。
结点数目相同的二叉树中,完全二叉树是路径长度最短的二叉树。
**权:**将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
**结点的带权路径长度:**从根结点到该结点之间的路径长度与该结点的权的乘积。
**树的带权路径长度:**树中所有叶子结点的带权路径长度之和。
2)构造哈夫曼树
顺序存储结构——一维结构数组
(1)定义结构
typedef struct {int weight; int parent, lch, rch;
}HTNode, * HuffmanTree;HuffmanTree H;
(2)步骤:
- 初始化HT [1…2n-1]:lch = rch = parent = 0;
- 输入初始几个叶子结点:置HT[1…n]的 weight 值;
- 进行以下n-1次合并,依次产生n-1个结点HT[i],i = n + 1…2n-1:
- 在HT[1…i-1]中选两个未被选过(从parent ==0 的结点中选)的weight最小的两个结点 HT[S1] 和 HT[S2],s1、s2为两个最小结点下标;
- 修改 HT[s1] 和 HT[s2] 的parent值:HT[s1].parent = i; HT[s2] .parent = i;
- 修改新产生的HT[i]:
HT[i].weight = HT[s1].weight + HT[s2].weight;
HTli].Ich = s1;
HT[i].rch = s2;
void CreatHuffmanTree(HuffmanTree& HT, int n) { //构造哈夫曼树--哈夫曼算法if (n <= 1) return;int m = 2 * n - 1; // 数组共2n-1个元素HT = new HTNode[m + 1]; // 动态分配内存,0号单元未用,HT[m]表示根结点// 初始化2n-1个元素的lch、rch、parent为0for (int i = 1; i <= m; ++i) {HT[i].lch = HT[i].rch = HT[i].parent = 0;}// 输入前n个元素的weight值cout << "请输入" << n << "个字符的频率:" << endl;for (int i = 1; i <= n; ++i) {cin >> HT[i].weight;}// 构建哈夫曼树for (int i = n + 1; i <= m; i++) {int s1, s2;Select(HT, i - 1, s1, s2);HT[s1].parent = i;HT[s2].parent = i;HT[i].lch = s1;HT[i].rch = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}
(3)总代码:
权值为整数:
#include <iostream>
#include <limits.h>using namespace std;// 定义哈夫曼树节点结构
typedef struct {int weight;int parent, lch, rch;
} HTNode;typedef HTNode* HuffmanTree;// 选择两个双亲域为0且权值最小的结点
void Select(const HTNode* HT, int i, int& s1, int& s2) {s1 = s2 = -1;int min1 = INT_MAX, min2 = INT_MAX;for (int j = 1; j <= i; ++j) {if (HT[j].parent == 0 && HT[j].weight < min1) {min2 = min1;s2 = s1;min1 = HT[j].weight;s1 = j;}else if (HT[j].parent == 0 && HT[j].weight < min2) {min2 = HT[j].weight;s2 = j;}}
}void CreatHuffmanTree(HuffmanTree& HT, int n) { //构造哈夫曼树--哈夫曼算法if (n <= 1) return;int m = 2 * n - 1; // 数组共2n-1个元素HT = new HTNode[m + 1]; // 动态分配内存,0号单元未用,HT[m]表示根结点// 初始化2n-1个元素的lch、rch、parent为0for (int i = 1; i <= m; ++i) {HT[i].lch = HT[i].rch = HT[i].parent = 0;}// 输入前n个元素的weight值cout << "请输入" << n << "个字符的频率:" << endl;for (int i = 1; i <= n; ++i) {cin >> HT[i].weight;}// 构建哈夫曼树for (int i = n + 1; i <= m; i++) {int s1, s2;Select(HT, i - 1, s1, s2);HT[s1].parent = i;HT[s2].parent = i;HT[i].lch = s1;HT[i].rch = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}int main() {int n;cout << "请输入叶子节点的数量:";cin >> n;HuffmanTree HT;CreatHuffmanTree(HT, n);// 打印哈夫曼树(示例)cout << "哈夫曼树构造完成,打印结果如下:" << endl;for (int i = 1; i < 2 * n; ++i) {cout << "Node " << i << ": Weight=" << HT[i].weight<< ", Parent=" << HT[i].parent<< ", Left Child=" << HT[i].lch<< ", Right Child=" << HT[i].rch << endl;}delete[] HT; // 释放动态分配的内存return 0;
}
权值为浮点数
#include <iostream>
#include <limits.h> // 如果不再使用 INT_MAX,可以不需要这个头文件using namespace std;// 定义哈夫曼树节点结构,将 weight 改为 double 类型
typedef struct {double weight; // 权值改为 double 类型int parent, lch, rch;
} HTNode;typedef HTNode* HuffmanTree;// 选择两个双亲域为0且权值最小的结点
void Select(const HTNode* HT, int i, int& s1, int& s2) {s1 = s2 = -1;double min1 = DBL_MAX, min2 = DBL_MAX; // 使用 DBL_MAX 作为最大值初始化for (int j = 1; j <= i; ++j) {if (HT[j].parent == 0 && HT[j].weight < min1) {min2 = min1;s2 = s1;min1 = HT[j].weight;s1 = j;}else if (HT[j].parent == 0 && HT[j].weight < min2) {min2 = HT[j].weight;s2 = j;}}
}void CreatHuffmanTree(HuffmanTree& HT, int n) { //构造哈夫曼树--哈夫曼算法if (n <= 1) return;int m = 2 * n - 1; // 数组共2n-1个元素HT = new HTNode[m + 1]; // 动态分配内存,0号单元未用,HT[m]表示根结点// 初始化2n-1个元素的lch、rch、parent为0for (int i = 1; i <= m; ++i) {HT[i].lch = HT[i].rch = HT[i].parent = 0;HT[i].weight = 0.0; // 初始化 weight 为 0.0}// 输入前n个元素的weight值cout << "请输入" << n << "个字符的小数频率:" << endl;for (int i = 1; i <= n; ++i) {cin >> HT[i].weight;}// 构建哈夫曼树for (int i = n + 1; i <= m; i++) {int s1, s2;Select(HT, i - 1, s1, s2);HT[s1].parent = i;HT[s2].parent = i;HT[i].lch = s1;HT[i].rch = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}int main() {int n;cout << "请输入叶子节点的数量:";cin >> n;HuffmanTree HT;CreatHuffmanTree(HT, n);// 打印哈夫曼树(示例)cout << "哈夫曼树构造完成,打印结果如下:" << endl;for (int i = 1; i <= 2 * n - 1; ++i) { // 注意这里应该是 2*n-1 而不是 2*ncout << "Node " << i << ": Weight=" << HT[i].weight<< ", Parent=" << HT[i].parent<< ", Left Child=" << HT[i].lch<< ", Right Child=" << HT[i].rch << endl;}delete[] HT; // 释放动态分配的内存return 0;
}
(4)运行结果:
3)哈夫曼编码
在远程通讯中,要将待传字符转换成由二进制的字符串:
若将编码设计为长度不等的二进制编码,即让待传字符串中出现次数较多的字符采用尽可能短的编码,则转换的二进制字符串便可能减少。
问题1 :什么样的前缀码能使得电文总长最短?
——哈夫曼编码
方法:
1、统计字符集中每个字符在电文中出现的平均概率(概率越大要求编码越短)。
2、利用哈夫曼树的特点:权越大的叶子离根越近;将每个字符的概率值作为权值,构造哈夫曼树。 则概率越大的结点,路径越短。
3、在哈夫曼树的每个分支上标上0或1:
- 结点的左分支标0,右分支桥 1。
- 把从根到每个吐子的路径上的标号连接起来,作为该叶子代表的字符的编码。
问题2 :为什么哈夫曼编码能够保证是前缀编码?
因为没有一片树叶是另一片树叶的祖先,所以每个叶结点的编码就不可能是其它叶结点编码的前缀。
问题 3 :为什么哈夫曼编码能够保证字符编码总长最短?
因为哈夫曼树的带权路径长度最短,故字符编码的总长最短。
- 性质1 哈夫曼编码是前缀码
- 性质2 哈夫曼编码是最优前缀码
算法实现:
// 从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中
void CreatHuffmanCode(const HuffmanTree& HT, HuffmanCode& HC, int n) {HC = new char*[n + 1]; // 分配n个字符编码的头指针数组char* cd = new char[n]; // 分配临时存放编码的动态数组空间cd[n - 1] = '\0'; // 编码结束符for (int i = 1; i <= n; ++i) {int start = n - 1;int c = i;int f = HT[i].parent;// 从叶子结点开始向上回溯,直到根结点while (f != 0) {--start;if (HT[f].lch == c)cd[start] = '0'; // 结点c是f的左孩子,则生成代码0elsecd[start] = '1'; // 结点c是f的右孩子,则生成代码1c = f;f = HT[f].parent;}// 计算编码长度并分配适当的空间int codeLength = n - start;HC[i] = new char[codeLength];strncpy(HC[i], &cd[start], codeLength);HC[i][codeLength - 1] = '\0'; // 确保字符串以空字符终止}delete[] cd; // 释放临时空间
}
strncpy(HC[i], &cd[start], codeLength);
语句在C++中确实可以用于复制字符数组,但它有一些潜在的问题和局限性。特别是当你使用strncpy
时,如果目标缓冲区没有足够的空间来包含源字符串加上终止空字符(\0
),它不会自动添加终止空字符,这可能会导致后续操作出现问题。
此外,在现代C++中,更推荐使用std::string
来处理字符串,因为它们更安全、更方便,并且可以避免手动管理内存的复杂性和风险。
// 从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中
void CreatHuffmanCode(const HuffmanTree& HT, HuffmanCode& HC, int n) {HC.resize(n + 1); // 分配n个字符编码的空间for (int i = 1; i <= n; ++i) {string code = "";int c = i;int f = HT[i].parent;// 从叶子结点开始向上回溯,直到根结点while (f != 0) {if (HT[f].lch == c)code = '0' + code; // 结点c是f的左孩子,则生成代码0elsecode = '1' + code; // 结点c是f的右孩子,则生成代码1c = f;f = HT[f].parent;}HC[i] = code;}
}
总代码实现:
#include <iostream>
#include <cstring> // 用于 strcpy 和 strlen
#include <limits> // 用于 std::numeric_limitsusing namespace std;// 定义哈夫曼树节点结构
typedef struct HTNode {double weight; // 权重改为 double 类型int parent, lch, rch;
} HTNode;typedef HTNode* HuffmanTree;// 定义哈夫曼编码结构
typedef char** HuffmanCode;// 选择两个双亲域为0且权值最小的结点
void Select(const HTNode* HT, int i, int& s1, int& s2) {s1 = s2 = -1;double min1 = numeric_limits<double>::max(), min2 = numeric_limits<double>::max();for (int j = 1; j <= i; ++j) {if (HT[j].parent == 0 && HT[j].weight < min1) {min2 = min1;s2 = s1;min1 = HT[j].weight;s1 = j;} else if (HT[j].parent == 0 && HT[j].weight < min2) {min2 = HT[j].weight;s2 = j;}}
}// 构造哈夫曼树--哈夫曼算法
void CreatHuffmanTree(HuffmanTree &HT, int n) {if (n <= 1) return;int m = 2 * n - 1; // 数组共2n-1个元素HT = new HTNode[m + 1]; // 动态分配内存,0号单元未用,HT[m]表示根结点// 初始化2n-1个元素的lch、rch、parent为0for (int i = 1; i <= m; ++i) {HT[i].lch = HT[i].rch = HT[i].parent = 0;HT[i].weight = 0.0; // 初始化权重为 0.0}// 输入前n个元素的weight值cout << "请输入" << n << "个字符的频率(浮点数):" << endl;for (int i = 1; i <= n; ++i) {cin >> HT[i].weight;}// 构建哈夫曼树for (int i = n + 1; i <= m; i++) {int s1, s2;Select(HT, i - 1, s1, s2);HT[s1].parent = i;HT[s2].parent = i;HT[i].lch = s1;HT[i].rch = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}// 从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode& HC, int n) {HC = new char*[n + 1]; // 分配n个字符编码的头指针数组char* cd = new char[n]; // 分配临时存放编码的动态数组空间cd[n - 1] = '\0'; // 编码结束符for (int i = 1; i <= n; ++i) {int start = n - 1;int c = i;int f = HT[i].parent;// 从叶子结点开始向上回溯,直到根结点while (f != 0) {--start;if (HT[f].lch == c)cd[start] = '0'; // 结点c是f的左孩子,则生成代码0elsecd[start] = '1'; // 结点c是f的右孩子,则生成代码1c = f;f = HT[f].parent;}// 计算编码长度并分配适当的空间int codeLength = n - start;HC[i] = new char[codeLength];strncpy(HC[i], &cd[start], codeLength);HC[i][codeLength - 1] = '\0'; // 确保字符串以空字符终止}delete[] cd; // 释放临时空间
}// 测试函数
int main() {int n;cout << "请输入叶子节点的数量:";cin >> n;HuffmanTree HT;CreatHuffmanTree(HT, n);HuffmanCode HC;CreatHuffmanCode(HT, HC, n);// 打印哈夫曼编码cout << "哈夫曼编码如下:" << endl;for (int i = 1; i <= n; ++i) {cout << "Character " << i << ": " << HC[i] << endl;}// 清理资源for (int i = 1; i <= n; ++i) {delete[] HC[i];}delete[] HC;delete[] HT;return 0;
}
改进后的代码:
#include <iostream>
#include <vector>
#include <string>
#include <limits>using namespace std;// 定义哈夫曼树节点结构
typedef struct HTNode {double weight; // 权重改为 double 类型int parent, lch, rch;
} HTNode;typedef HTNode* HuffmanTree;// 选择两个双亲域为0且权值最小的结点
void Select(const vector<HTNode>& HT, int i, int& s1, int& s2) {s1 = s2 = -1;double min1 = numeric_limits<double>::max(), min2 = numeric_limits<double>::max();for (int j = 1; j <= i; ++j) {if (HT[j].parent == 0 && HT[j].weight < min1) {min2 = min1;s2 = s1;min1 = HT[j].weight;s1 = j;} else if (HT[j].parent == 0 && HT[j].weight < min2) {min2 = HT[j].weight;s2 = j;}}
}// 构造哈夫曼树--哈夫曼算法
void CreatHuffmanTree(vector<HTNode>& HT, int n) {if (n <= 1) return;int m = 2 * n - 1; // 数组共2n-1个元素// 初始化2n-1个元素的lch、rch、parent为0,权重为0.0HT.resize(m + 1);for (int i = 1; i <= m; ++i) {HT[i] = {0.0, 0, 0, 0};}// 输入前n个元素的weight值cout << "请输入" << n << "个字符的频率(浮点数):" << endl;for (int i = 1; i <= n; ++i) {cin >> HT[i].weight;}// 构建哈夫曼树for (int i = n + 1; i <= m; i++) {int s1, s2;Select(HT, i - 1, s1, s2);HT[s1].parent = i;HT[s2].parent = i;HT[i].lch = s1;HT[i].rch = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}// 从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中
void CreatHuffmanCode(const vector<HTNode>& HT, vector<string>& HC, int n) {HC.resize(n + 1); // 分配n个字符编码的空间for (int i = 1; i <= n; ++i) {string code = "";int c = i;int f = HT[i].parent;// 从叶子结点开始向上回溯,直到根结点while (f != 0) {if (HT[f].lch == c)code = '0' + code; // 结点c是f的左孩子,则生成代码0elsecode = '1' + code; // 结点c是f的右孩子,则生成代码1c = f;f = HT[f].parent;}HC[i] = code;}
}// 测试函数
int main() {int n;cout << "请输入叶子节点的数量:";cin >> n;vector<HTNode> HT;CreatHuffmanTree(HT, n);vector<string> HC;CreatHuffmanCode(HT, HC, n);// 打印哈夫曼编码cout << "哈夫曼编码如下:" << endl;for (int i = 1; i <= n; ++i) {cout << "Character " << i << ": " << HC[i] << endl;}return 0;
}
改进后:
#include <iostream>
#include <cstring> // 用于 strcpy 和 strlen
#include <limits> // 用于 std::numeric_limitsusing namespace std;// 定义哈夫曼树节点结构
typedef struct HTNode {double weight; // 权重改为 double 类型int parent, lch, rch;
} HTNode;typedef HTNode* HuffmanTree;// 定义哈夫曼编码结构
typedef char** HuffmanCode;// 选择两个双亲域为0且权值最小的结点
void Select(const HTNode* HT, int i, int& s1, int& s2) {s1 = s2 = -1;double min1 = numeric_limits<double>::max(), min2 = numeric_limits<double>::max();for (int j = 1; j <= i; ++j) {if (HT[j].parent == 0 && HT[j].weight < min1) {min2 = min1;s2 = s1;min1 = HT[j].weight;s1 = j;} else if (HT[j].parent == 0 && HT[j].weight < min2) {min2 = HT[j].weight;s2 = j;}}
}// 构造哈夫曼树--哈夫曼算法
void CreatHuffmanTree(HuffmanTree &HT, int n) {if (n <= 1) return;int m = 2 * n - 1; // 数组共2n-1个元素HT = new HTNode[m + 1]; // 动态分配内存,0号单元未用,HT[m]表示根结点// 初始化2n-1个元素的lch、rch、parent为0for (int i = 1; i <= m; ++i) {HT[i].lch = HT[i].rch = HT[i].parent = 0;HT[i].weight = 0.0; // 初始化权重为 0.0}// 输入前n个元素的weight值cout << "请输入" << n << "个字符的频率):" << endl;for (int i = 1; i <= n; ++i) {cin >> HT[i].weight;}// 构建哈夫曼树for (int i = n + 1; i <= m; i++) {int s1, s2;Select(HT, i - 1, s1, s2);HT[s1].parent = i;HT[s2].parent = i;HT[i].lch = s1;HT[i].rch = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;}
}// 从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode& HC, int n) {HC = new char*[n + 1]; // 分配n个字符编码的头指针数组for (int i = 1; i <= n; ++i) {string code = ""; // 使用string来构建编码int c = i;int f = HT[i].parent;// 从叶子结点开始向上回溯,直到根结点while (f != 0) {if (HT[f].lch == c)code = '0' + code; // 结点c是f的左孩子,则生成代码0elsecode = '1' + code; // 结点c是f的右孩子,则生成代码1c = f;f = HT[f].parent;}// 将string转换为C风格字符串并分配适当的空间HC[i] = new char[code.length() + 1];strcpy(HC[i], code.c_str());}
}// 测试函数
int main() {int n;cout << "请输入叶子节点的数量:";cin >> n;if (n <= 0) {cerr << "叶子节点数量必须大于0." << endl;return 1;}HuffmanTree HT;CreatHuffmanTree(HT, n);HuffmanCode HC;CreatHuffmanCode(HT, HC, n);// 打印哈夫曼编码cout << "哈夫曼编码如下:" << endl;for (int i = 1; i <= n; ++i) {cout << "Character " << i << ": " << HC[i] << endl;}// 清理资源for (int i = 1; i <= n; ++i) {delete[] HC[i];}delete[] HC;delete[] HT;return 0;
}
运行结果:
相关文章:

C/C++ 数据结构与算法【哈夫曼树】 哈夫曼树详细解析【日常学习,考研必备】带图+详细代码
哈夫曼树(最优二叉树) 1)基础概念 **路径:**从树中一个结点到另一个结点之间的分支构成这两个结点间的路径。 **结点的路径长度:**两结点间路径上的分支数。 **树的路径长度:**从树根到每一个结点的路径…...

基于NodeMCU的物联网窗帘控制系统设计
最终效果 基于NodeMCU的物联网窗帘控制系统设计 项目介绍 该项目是“物联网实验室监测控制系统设计(仿智能家居)”项目中的“家电控制设计”中的“窗帘控制”子项目,最前者还包括“物联网设计”、“环境监测设计”、“门禁系统设计计”和“小…...

喜报 | 擎创科技入围上海市优秀信创解决方案
近日,由上海市经信委组织的“2024年上海市优秀信创解决方案”征集遴选活动圆满落幕,擎创科技凭借实践经验优秀的《擎创夏洛克智能预警与应急处置解决方案》成功入选“2024年上海市优秀信创解决方案”名单。 为激发创新活力,发挥标杆作用&…...

windows10下使用沙盒多开uiautoanimation可行性验证
文章目录 ⭐前言⭐sandboxie下载使用⭐pyinstaller打包python的uiautoanimation成exe⭐结论⭐结束 ⭐前言 大家好,我是yma16,本文分享windows下使用沙盒多开uiautoanimation可行性验证。 背景 实现多开应用程序从而进行自动化控制,批量处理大…...

电脑报错wsdprintproxy.dll丢失?修复wsdprintproxy.dll文件缺失的实用方法
在使用电脑的过程中,我们可能会遇到各种各样的错误提示,其中之一就是系统提示wsdprintproxy.dll文件丢失。这个DLL文件是Windows操作系统中的一个重要组件,它通常与Windows的打印功能相关。当这个文件丢失或损坏时,可能会导致打印…...
Kubernetes 的资源管理方式
集群架构 Docker 是每一个节点(包括 Master 节点和 Node 节点)的运行时环境。 kubelet 负责控制所有容器的启动和停止等,保证每个节点(包括 Master 节点和 Node 节点)正常工作,并且帮助 Node 节点和 Maste…...

layui动态拼接生成下拉框验证必填项失效问题
利用 jQuery 动态拼接下拉框时,lay-verify"required" 失效了,有以下几种原因。 1. <form></form>标签 加入 layui 类,class"layui-form" 。提交按钮上加自动提交,lay-submit ""; 。需…...
VUE3+VITE简单的跨域代理配置
出于安全考虑,未设置前端白名单,前端开发时,需要配置代理。 在本地创建一个虚拟服务器,发送请求数据,同时接受请求的数据, 利用服务器与服务器间,交互,不会有跨域问题,也…...

Xdebug
1、开启xdebug扩展 2、修改一下php.ini文件 xdebug.remote_enable 1 xdebug.remote_autostart 13、vscode安装插件php debug 4、生成launch.json文件,好像啥都不用改 5、vscode没有配置php路径的,需要去配置: 6、发起请求 8、代码断…...

IDEA | SpringBoot 项目中使用 Apifox 上传接口
目录 1 安装 Apifox Helper 插件2 获取 Apifox 的 API 访问令牌3 IDEA 中设置 API 访问令牌4 IDEA 中上传接口5 常见问题5.1 如何自动设置目录名5.2 如何自动设置接口名5.3 如何更改上传位置 Apifox 官方指南: https://apifox.com/help/applications-and-p…...
列表分页返回对象
列表分页返回对象 仅针对于新项目,因为一般进入公司后项目都是已经搭建好的,只需要在原有框架基础上操作就可以了,但是遇到从0开始的项目并且还没有架构需要自己搭框架的时候就需要自己想办法找各种封装格式。 下面记录分页列表返回的封装格式…...

微软edge浏览器 v131.0.2903.99便携版
前言 Microsoft Edge浏览器是个新浏览器,它用起来很简单,界面也很清爽。这个浏览器功能特别多,里面还带了微软的小助手Contana,能帮用户做不少贴心的事儿。它支持安装各种小工具(插件),还能在网…...
Prometheus 专栏 —— Prometheus入门介绍
Prometheus 是? Prometheus 是一个开源的服务监控系统和时序数据库,主要用于收集、存储、查询和告警时间序列数据,这些数据通常反映了系统或者应用的状态或性能 Prometheus 的基本功能是? 数据采集数据存储数据查询告警通知 Prometheus 监控核心组件?…...

元宇宙在教育行业主要有哪些应用场景?
近两年来,元宇宙风潮在全球范围内迅速掀起了一股新的浪潮,“元宇宙”已成为各行各业探索新发展方向的热门话题,教育行业亦不例外。那么元宇宙在教育行业主要有哪些应用场景呢? 以下为主要适用场景: 课程实践ÿ…...

JZ31 栈的压入、弹出序列
题目来源:栈的压入、弹出序列_牛客题霸_牛客网 题目:如下 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序…...

电脑缺失libcurl.dll怎么解决?详解电脑libcurl.dll文件丢失问题
一、libcurl.dll文件丢失的原因 libcurl.dll是一个用于处理URL传输的库文件,广泛应用于各种基于网络的应用程序。当这个文件丢失时,可能会导致相关应用程序无法正常运行。以下是libcurl.dll文件丢失的一些常见原因: 软件安装或卸载不完整&a…...

Ribbon、Nacos
目录 Ribbon 常见负载算法 切换负载均衡算法 Nacos注册中心 下载和运行 微服务模块接入注册中心 consumer-80模块 配置类 Controller Nacos配置中心 Nacos分类配置(实现配置隔离) DataID方案 Group方案 Namespace方案 总结 Ribbon Ribbon…...

SpringCloudAlibaba实战入门之路由网关Gateway初体验(十一)
Spring Cloud 原先整合 Zuul 作为网关组件,Zuul 由 Netflix 公司提供的,现在已经不维护了。后面 Netflix 公司又出来了一个 Zuul2.0 网关,但由于一直没有发布稳定版本,所以 Spring Cloud 等不及了就自己推出一个网关,已经不打算整合 zuul2.0 了。 一、什么是网关 1、顾明…...

【C语言练习(18)—指针传递参数练习】
C语言练习(18) 文章目录 C语言练习(18)前言问题问题解析 前言 指针的使用很方便参数之间的传递,通过交换数字,来练习函数之间指针传递数据。 问题 利用函数交换两个数字的大小 问题解析 例如a5;b10;想…...

外网访问 Docker 容器的可视化管理工具 DockerUI
DockerUI 是一个 docker 容器镜像的可视化图形化管理工具,DockerUI 可以用来轻松构建、管理和维护 docker 环境。让用户维护起来更方便。 本文就介绍如何安装使用 DockerUI 并结合路由侠内网穿透来访问 DockerUI。 第一步,安装 DockerUI 1,…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...