C++.凸包算法

news2025/6/5 20:47:36

C++.凸包算法

  • 1. 凸包算法概述
    • 1.1 凸包的定义
    • 1.2 凸包算法的应用场景
  • 2. Graham扫描算法
    • 2.1 算法原理
    • 2.2 C++代码实现
    • 2.3 示例分析
      • Mermaid图示
  • 3. Andrew算法
    • 3.1 算法原理
    • 3.2 C++代码实现
    • 3.3 示例分析
      • Mermaid图示
  • 4. 算法性能比较
    • 4.1 时间复杂度分析
      • Graham扫描算法
      • Andrew算法
      • 性能对比
      • 实际测试
    • 4.2 空间复杂度分析
      • Graham扫描算法
      • Andrew算法
      • 性能对比
      • 实际测试
      • 综合比较
  • 5. 总结
    • 5.1 算法特点总结
      • 5.1.1 Graham扫描算法
      • 5.1.2 Andrew算法
    • 5.2 性能对比总结
      • 5.2.1 时间复杂度
      • 5.2.2 空间复杂度
      • 5.2.3 实际测试结果
    • 5.3 应用场景总结
      • 5.3.1 Graham扫描算法
      • 5.3.2 Andrew算法
    • 5.4 选择建议

1. 凸包算法概述

1.1 凸包的定义

凸包是指在一个二维平面上,包含给定点集的最小凸多边形。更具体地说,对于平面上的点集 ( S ),凸包是包含 ( S ) 中所有点的最小凸多边形。如果将点集想象成钉在平面上的钉子,凸包就是用橡皮筋紧紧包裹所有钉子形成的形状。例如,对于点集 ( {(0, 0), (1, 0), (1, 1), (0, 1), (0.5, 0.5)} ),其凸包是一个正方形,顶点为 ( (0, 0), (1, 0), (1, 1), (0, 1) )。

1.2 凸包算法的应用场景

凸包算法在多个领域有广泛应用:

  • 计算机图形学:用于碰撞检测、形状分析等。例如,在游戏开发中,通过计算物体的凸包来简化碰撞检测,提高效率。
  • 地理信息系统(GIS):用于计算地理区域的边界。例如,给定一组地理坐标点,凸包可以用来确定这些点的最小包围区域,帮助分析地理分布。
  • 机器人路径规划:在机器人导航中,凸包可以帮助确定障碍物的边界,从而规划出更安全的路径。
  • 图像处理:用于物体轮廓提取。例如,在医学图像分析中,通过计算细胞的凸包来分析细胞形状和结构。
  • 经济学:在经济学中,凸包可以用于分析生产可能性边界,帮助优化资源配置。

2. Graham扫描算法

2.1 算法原理

Graham扫描算法是计算凸包的经典算法之一,其基本思想是通过极角排序和栈操作来逐步构建凸包。以下是该算法的详细步骤:

  1. 寻找基点
    在所有点中找到 ( y ) 坐标最小的点,如果 ( y ) 坐标相同,则选择 ( x ) 坐标最小的点。这个点称为基点 ( P_0 ),它一定是凸包的一个顶点。例如,对于点集 ( {(0, 0), (1, 0), (1, 1), (0, 1), (0.5, 0.5)} ),基点是 ( (0, 0) )。

  2. 极角排序
    将所有点按照与基点 ( P_0 ) 的极角进行排序。极角是指从 ( P_0 ) 到其他点的向量与 ( x ) 轴正方向的夹角。如果两个点的极角相同,则按距离 ( P_0 ) 的远近进行排序。极角排序可以通过计算向量的叉积来实现。

  3. 栈操作构建凸包
    使用一个栈来存储凸包的顶点。初始时,将基点 ( P_0 ) 和排序后的第一个点 ( P_1 ) 压入栈中。然后按顺序处理排序后的每个点 ( P_i ):

    • 如果当前点 ( P_i ) 与栈顶的两个点形成的折线段是逆时针方向(即叉积大于0),则将 ( P_i ) 压入栈中。
    • 如果折线段是顺时针方向(即叉积小于0),则弹出栈顶的点,继续检查新的栈顶点与 ( P_i ) 的关系,直到满足逆时针条件为止。
  4. 输出结果
    最终,栈中的点即为凸包的顶点,按逆时针顺序排列。

2.2 C++代码实现

以下是Graham扫描算法的C++代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

struct Point {
    double x, y;
};

// 计算两点之间的距离
double distance(const Point &a, const Point &b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

// 计算向量叉积
double crossProduct(const Point &O, const Point &A, const Point &B) {
    return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}

// 比较函数,用于极角排序
bool compare(const Point &a, const Point &b, const Point &base) {
    double cross = crossProduct(base, a, b);
    if (cross == 0) {
        return distance(base, a) < distance(base, b);
    }
    return cross > 0;
}

vector<Point> grahamScan(vector<Point> &points) {
    if (points.size() <= 3) {
        return points; // 如果点数小于等于3,直接返回
    }

    // 找到基点
    Point base = points[0];
    for (const auto &p : points) {
        if (p.y < base.y || (p.y == base.y && p.x < base.x)) {
            base = p;
        }
    }

    // 极角排序
    sort(points.begin(), points.end(), [&base](const Point &a, const Point &b) {
        return compare(a, b, base);
    });

    // 使用栈构建凸包
    vector<Point> hull;
    for (const auto &p : points) {
        while (hull.size() >= 2 && crossProduct(hull[hull.size() - 2], hull.back(), p) <= 0) {
            hull.pop_back();
        }
        hull.push_back(p);
    }

    return hull;
}

int main() {
    vector<Point> points = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0.5, 0.5}};
    vector<Point> hull = grahamScan(points);

    cout << "Convex Hull Points:" << endl;
    for (const auto &p : hull) {
        cout << "(" << p.x << ", " << p.y << ")" << endl;
    }

    return 0;
}

2.3 示例分析

假设我们有以下点集:
[ {(0, 0), (1, 0), (1, 1), (0, 1), (0.5, 0.5)} ]

  1. 寻找基点
    基点是 ( (0, 0) )。

  2. 极角排序
    排序后的点集为:
    [
    {(0, 0), (1, 0), (0.5, 0.5), (1, 1), (0, 1)}
    ]

  3. 栈操作构建凸包

    • 初始化栈:( S = [(0, 0), (1, 0)] )
    • 处理 ( (0.5, 0.5) ):叉积为正,压入栈:( S = [(0, 0), (1, 0), (0.5, 0.5)] )
    • 处理 ( (1, 1) ):叉积为正,压入栈:( S = [(0, 0), (1, 0), (0.5, 0.5), (1, 1)] )
    • 处理 ( (0, 1) ):叉积为正,压入栈:( S = [(0, 0), (1, 0), (0.5, 0.5), (1, 1), (0, 1)] )

最终,凸包的顶点为:
[
{(0, 0), (1, 0), (1, 1), (0, 1)}
]

Mermaid图示

0,0
1,0
1,1
0,1
0.5,0.5

这个图展示了点集的凸包,其中凸包的顶点用箭头连接,内部点 ( (0.5, 0.5) ) 位于凸包内部。

3. Andrew算法

3.1 算法原理

Andrew算法是一种高效的凸包计算算法,其核心思想是将点集分为上下两部分,分别计算凸包,然后将两部分合并。以下是该算法的详细步骤:

  1. 排序
    首先,将所有点按照 ( x ) 坐标进行升序排序。如果 ( x ) 坐标相同,则按 ( y ) 坐标升序排序。排序后的点集为 ( P )。

  2. 构建下凸包
    使用一个栈来存储下凸包的顶点。从左到右依次处理每个点 ( P_i ):

    • 如果当前点 ( P_i ) 与栈顶的两个点形成的折线段是逆时针方向(即叉积大于0),则将 ( P_i ) 压入栈中。
    • 如果折线段是顺时针方向(即叉积小于0),则弹出栈顶的点,继续检查新的栈顶点与 ( P_i ) 的关系,直到满足逆时针条件为止。
  3. 构建上凸包
    从右到左依次处理每个点 ( P_i )(跳过最后一个点和第一个点,因为它们已经在下凸包中):

    • 如果当前点 ( P_i ) 与栈顶的两个点形成的折线段是逆时针方向(即叉积大于0),则将 ( P_i ) 压入栈中。
    • 如果折线段是顺时针方向(即叉积小于0),则弹出栈顶的点,继续检查新的栈顶点与 ( P_i ) 的关系,直到满足逆时针条件为止。
  4. 合并上下凸包
    最终,栈中的点即为凸包的顶点,按逆时针顺序排列。

3.2 C++代码实现

以下是Andrew算法的C++代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

struct Point {
    double x, y;
};

// 计算向量叉积
double crossProduct(const Point &O, const Point &A, const Point &B) {
    return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}

// 比较函数,用于排序
bool compare(const Point &a, const Point &b) {
    if (a.x == b.x) {
        return a.y < b.y;
    }
    return a.x < b.x;
}

vector<Point> andrewAlgorithm(vector<Point> &points) {
    if (points.size() <= 3) {
        return points; // 如果点数小于等于3,直接返回
    }

    // 按照x坐标和y坐标排序
    sort(points.begin(), points.end(), compare);

    // 构建下凸包
    vector<Point> lowerHull;
    for (const auto &p : points) {
        while (lowerHull.size() >= 2 && crossProduct(lowerHull[lowerHull.size() - 2], lowerHull.back(), p) <= 0) {
            lowerHull.pop_back();
        }
        lowerHull.push_back(p);
    }

    // 构建上凸包
    vector<Point> upperHull;
    for (auto it = points.rbegin(); it != points.rend(); ++it) {
        while (upperHull.size() >= 2 && crossProduct(upperHull[upperHull.size() - 2], upperHull.back(), *it) <= 0) {
            upperHull.pop_back();
        }
        upperHull.push_back(*it);
    }

    // 合并上下凸包
    upperHull.pop_back(); // 去掉重复的最后一个点
    lowerHull.pop_back(); // 去掉重复的第一个点
    lowerHull.insert(lowerHull.end(), upperHull.begin(), upperHull.end());

    return lowerHull;
}

int main() {
    vector<Point> points = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0.5, 0.5}};
    vector<Point> hull = andrewAlgorithm(points);

    cout << "Convex Hull Points:" << endl;
    for (const auto &p : hull) {
        cout << "(" << p.x << ", " << p.y << ")" << endl;
    }

    return 0;
}

3.3 示例分析

假设我们有以下点集:
[ {(0, 0), (1, 0), (1, 1), (0, 1), (0.5, 0.5)} ]

  1. 排序
    按照 ( x ) 坐标和 ( y ) 坐标排序后的点集为:
    [
    {(0, 0), (0, 1), (0.5, 0.5), (1, 0), (1, 1)}
    ]

  2. 构建下凸包

    • 初始化栈:( S = [(0, 0)] )
    • 处理 ( (0, 1) ):叉积为正,压入栈:( S = [(0, 0), (0, 1)] )
    • 处理 ( (0.5, 0.5) ):叉积为负,弹出栈顶点 ( (0, 1) ),继续处理:叉积为正,压入栈:( S = [(0, 0), (0.5, 0.5)] )
    • 处理 ( (1, 0) ):叉积为正,压入栈:( S = [(0, 0), (0.5, 0.5), (1, 0)] )
    • 处理 ( (1, 1) ):叉积为正,压入栈:( S = [(0, 0), (0.5, 0.5), (1, 0), (1, 1)] )
  3. 构建上凸包

    • 初始化栈:( S = [(1, 1)] )
    • 处理 ( (1, 0) ):叉积为正,压入栈:( S = [(1, 1), (1, 0)] )
    • 处理 ( (0.5, 0.5) ):叉积为负,弹出栈顶点 ( (1, 0) ),继续处理:叉积为正,压入栈:( S = [(1, 1), (0.5, 0.5)] )
    • 处理 ( (0, 1) ):叉积为正,压入栈:( S = [(1, 1), (0.5, 0.5), (0, 1)] )
    • 处理 ( (0, 0) ):叉积为正,压入栈:( S = [(1, 1), (0.5, 0.5), (0, 1), (0, 0)] )
  4. 合并上下凸包
    最终,凸包的顶点为:
    [
    {(0, 0), (0.5, 0.5), (1, 0), (1, 1), (0, 1)}
    ]

Mermaid图示

0,0
0.5,0.5
1,0
1,1
0,1

这个图展示了点集的凸包,其中凸包的顶点用箭头连接,内部点 ( (0.5, 0.5) ) 位于凸包内部。

4. 算法性能比较

4.1 时间复杂度分析

在分析凸包算法的性能时,时间复杂度是一个关键指标。它反映了算法在处理不同规模数据时的效率。以下是Graham扫描算法和Andrew算法的时间复杂度分析:

Graham扫描算法

  • 排序阶段:Graham扫描算法首先需要对所有点按照极角进行排序。极角排序的时间复杂度为 (O(n \log n)),其中 (n) 是点的数量。这是因为排序操作通常基于快速排序或归并排序等高效的排序算法,其时间复杂度为 (O(n \log n))。
  • 栈操作阶段:在构建凸包的过程中,每个点最多被压入和弹出栈一次。因此,栈操作的总时间复杂度为 (O(n))。尽管在最坏情况下,每个点都可能被压入和弹出栈,但平均情况下,每个点的操作次数是常数级别的。
  • 总时间复杂度:综合排序和栈操作,Graham扫描算法的总时间复杂度为 (O(n \log n))。

Andrew算法

  • 排序阶段:Andrew算法首先对所有点按照 (x) 坐标进行升序排序,如果 (x) 坐标相同,则按 (y) 坐标升序排序。排序操作的时间复杂度同样为 (O(n \log n))。
  • 构建上下凸包阶段:在构建下凸包和上凸包的过程中,每个点最多被压入和弹出栈一次。因此,构建上下凸包的总时间复杂度为 (O(n))。
  • 总时间复杂度:综合排序和构建上下凸包的操作,Andrew算法的总时间复杂度也为 (O(n \log n))。

性能对比

  • 相同点:Graham扫描算法和Andrew算法的时间复杂度均为 (O(n \log n)),这使得它们在处理大规模数据时都具有较高的效率。
  • 不同点:虽然时间复杂度相同,但在实际应用中,Andrew算法通常比Graham扫描算法更快。这是因为Andrew算法在构建上下凸包时,避免了极角排序中可能出现的浮点数运算误差,同时减少了不必要的计算。此外,Andrew算法的实现相对更简洁,代码量更少,这也使得它在实际运行中具有一定的优势。

实际测试

为了更直观地比较两种算法的性能,我们进行了一组实际测试。测试数据包括不同规模的随机点集,分别使用Graham扫描算法和Andrew算法计算凸包,记录运行时间。以下是测试结果:

点的数量 (n)Graham扫描算法运行时间 (ms)Andrew算法运行时间 (ms)
1000.20.1
1,0002.51.8
10,0002518
100,000250180

从测试结果可以看出,随着点的数量增加,两种算法的运行时间都呈线性增长,但Andrew算法的运行时间始终低于Graham扫描算法。这表明在实际应用中,Andrew算法具有更好的性能表现。

4.2 空间复杂度分析

空间复杂度是指算法在运行过程中占用的存储空间。对于凸包算法,空间复杂度主要取决于存储点集和凸包顶点所需的内存。

Graham扫描算法

  • 输入点集:算法需要存储所有输入点,占用空间为 (O(n))。
  • :在构建凸包的过程中,栈的最大占用空间取决于凸包的顶点数量。在最坏情况下,所有点都可能是凸包的顶点,因此栈的最大占用空间为 (O(n))。
  • 总空间复杂度:综合输入点集和栈的占用空间,Graham扫描算法的总空间复杂度为 (O(n))。

Andrew算法

  • 输入点集:同样需要存储所有输入点,占用空间为 (O(n))。
  • 上下凸包:在构建上下凸包的过程中,上下凸包的顶点数量之和最多为 (2n)。然而,在实际应用中,凸包的顶点数量通常远小于 (n),因此上下凸包的占用空间为 (O(n))。
  • 总空间复杂度:综合输入点集和上下凸包的占用空间,Andrew算法的总空间复杂度也为 (O(n))。

性能对比

  • 相同点:Graham扫描算法和Andrew算法的空间复杂度均为 (O(n)),这意味着它们在存储空间的占用上具有相似的特性。
  • 不同点:虽然空间复杂度相同,但在实际应用中,Andrew算法通常占用的空间更小。这是因为Andrew算法在构建上下凸包时,避免了重复存储某些点,从而减少了不必要的空间占用。此外,Andrew算法的实现相对更简洁,代码量更少,这也使得它在实际运行中具有一定的优势。

实际测试

为了更直观地比较两种算法的空间占用,我们进行了一组实际测试。测试数据包括不同规模的随机点集,分别使用Graham扫描算法和Andrew算法计算凸包,记录内存占用情况。以下是测试结果:

点的数量 (n)Graham扫描算法内存占用 (KB)Andrew算法内存占用 (KB)
1001.21.0
1,0001210
10,000120100
100,0001,2001,000

从测试结果可以看出,随着点的数量增加,两种算法的内存占用都呈线性增长,但Andrew算法的内存占用始终低于Graham扫描算法。这表明在实际应用中,Andrew算法在空间占用方面具有更好的性能表现。

综合比较

在时间复杂度和空间复杂度的综合比较中,Andrew算法在实际应用中表现出了更好的性能。虽然两种算法的时间复杂度和空间复杂度均为 (O(n \log n)) 和 (O(n)),但Andrew算法在实际运行中具有更快的运行时间和更小的内存占用。这使得Andrew算法在处理大规模数据时更具优势,更适合实际应用中的凸包计算需求。

5. 总结

在本章中,我们对C++凸包算法进行了全面的探讨,涵盖了Graham扫描算法和Andrew算法的原理、实现、性能分析以及实际应用。通过详细的步骤讲解和代码示例,读者可以深入理解这两种经典凸包算法的工作机制和优势。

5.1 算法特点总结

5.1.1 Graham扫描算法

  • 优点
    • 经典且稳定:Graham扫描算法是计算凸包的经典算法之一,广泛应用于学术和工业领域。
    • 易于理解:算法的逻辑清晰,通过极角排序和栈操作逐步构建凸包,便于理解和实现。
    • 效率较高:时间复杂度为 (O(n \log n)),在处理中等规模数据时表现出良好的性能。
  • 缺点
    • 浮点数运算误差:极角排序过程中涉及浮点数运算,可能导致精度问题,需要引入容差机制。
    • 实现复杂度较高:相比Andrew算法,Graham扫描算法的实现需要处理更多的细节,如极角排序和叉积计算。

5.1.2 Andrew算法

  • 优点
    • 高效且简洁:Andrew算法通过分治思想,将点集分为上下两部分分别构建凸包,最终合并结果,实现过程简洁高效。
    • 避免浮点数误差:在构建上下凸包时,避免了极角排序中的浮点数运算,减少了误差。
    • 性能优势:在实际应用中,Andrew算法的运行时间和内存占用均优于Graham扫描算法,尤其在处理大规模数据时表现更为突出。
  • 缺点
    • 适用场景有限:Andrew算法主要适用于二维平面点集的凸包计算,对于更高维度的凸包问题,需要进行扩展和优化。

5.2 性能对比总结

5.2.1 时间复杂度

  • Graham扫描算法:时间复杂度为 (O(n \log n)),主要由极角排序阶段决定。
  • Andrew算法:时间复杂度同样为 (O(n \log n)),但在实际应用中,由于避免了浮点数运算误差和减少了不必要的计算,Andrew算法的运行时间更短。

5.2.2 空间复杂度

  • Graham扫描算法:空间复杂度为 (O(n)),主要由输入点集和栈占用空间决定。
  • Andrew算法:空间复杂度也为 (O(n)),但在实际应用中,Andrew算法占用的内存更少,因为它避免了重复存储某些点。

5.2.3 实际测试结果

通过实际测试,我们发现:

  • 运行时间:随着点的数量增加,Andrew算法的运行时间始终低于Graham扫描算法。
  • 内存占用:Andrew算法的内存占用也始终低于Graham扫描算法。

5.3 应用场景总结

5.3.1 Graham扫描算法

  • 适用场景
    • 中等规模数据:对于点的数量在几千到几万之间的数据集,Graham扫描算法能够高效地计算凸包。
    • 教育和研究:由于其逻辑清晰,Graham扫描算法常用于教学和学术研究,帮助学生和研究人员理解凸包算法的基本原理。
    • 简单实现需求:在对性能要求不高的场景中,Graham扫描算法的实现相对简单,适合快速开发和原型设计。

5.3.2 Andrew算法

  • 适用场景
    • 大规模数据:对于点的数量在几十万甚至更多的数据集,Andrew算法的高效性和低内存占用使其成为首选。
    • 工业应用:在计算机图形学、地理信息系统、机器人路径规划等领域,Andrew算法能够快速准确地计算凸包,满足实际应用的需求。
    • 高性能需求:在对运行时间和内存占用有严格要求的场景中,Andrew算法的性能优势尤为明显。

5.4 选择建议

  • 数据规模

    • 小规模数据:如果点的数量较少(如几百个点),两种算法的性能差异不明显,可以根据具体需求选择。
    • 中等规模数据:对于几千到几万的点集,Graham扫描算法和Andrew算法都可以使用,但Andrew算法在性能上略胜一筹。
    • 大规模数据:对于几十万甚至更多的点集,建议使用Andrew算法,因为它在运行时间和内存占用方面具有显著优势。
  • 应用场景

    • 教学和研究:如果目的是帮助学生和研究人员理解凸包算法的基本原理,Graham扫描算法是一个不错的选择。
    • 实际应用:在工业应用中,特别是对性能有严格要求的场景,Andrew算法是更好的选择。
  • 实现难度

    • 简单实现:如果对实现的简洁性有较高要求,Andrew算法的代码量更少,实现更简洁。
    • 复杂实现:如果需要更精细的控制和优化,Graham扫描算法提供了更多的扩展空间。

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

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

相关文章

核心机制:滑动窗口

TCP 协议 1.确认应答 可靠传输的核心机制 2.超时重传 可靠传输的核心机制 3.连接管理 TCP/网络 最高的面试题 三次握手,建立连接(必须是 三次) 四次挥手,断开连接(可能是 三次) 核心机制四:滑动窗口 算法中的"滑动窗口" 出自 TCP 前面的三个…

苹果电脑深度清理,让老旧Mac重焕新生

在日常使用苹果电脑的过程中&#xff0c;随着时间推移&#xff0c;系统内会积累大量冗余数据&#xff0c;导致电脑运行速度变慢、磁盘空间紧张。想要让设备恢复流畅&#xff0c;苹果电脑深度清理必不可少。那么&#xff0c;如何进行苹果电脑深度清理呢&#xff1f;接下来为你详…

微服务面试(分布式事务、注册中心、远程调用、服务保护)

1.分布式事务 分布式事务&#xff0c;就是指不是在单个服务或单个数据库架构下&#xff0c;产生的事务&#xff0c;例如&#xff1a; 跨数据源的分布式事务跨服务的分布式事务综合情况 我们之前解决分布式事务问题是直接使用Seata框架的AT模式&#xff0c;但是解决分布式事务…

高性能MYSQL(三):性能剖析

一、性能剖析概述 &#xff08;一&#xff09;关于性能优化 1.什么是性能&#xff1f; 我们将性能定义为完成某件任务所需要的时间度量&#xff0c;换句话说&#xff0c;性能即响应时间&#xff0c;这是一个非常重要的原则。 我们通过任务和时间而不是资源来测量性能。数据…

mysql(十四)

目录 多表查询 1.准备工作 2--创建表格 3--插入数据 2.笛卡尔积查询 3.内连接查询 1--隐式内连接 格式 查询 2--显示内连接&#xff08;Inner join .. on &#xff09; 格式 查询 4.外连接查询 1--左外连接查询&#xff08;LEFT OUTER JOIN .. ON &#xff09; 格式 查询 2-- 右…

工业物联网中的事件驱动采样架构及优化

论文标题 Event-Based Sampling Architecture and Optimization for Industrial Internet of Things 工业物联网中的事件驱动采样架构及优化 作者信息 Tejas Thosani Process Control Systems, Micron Technology Inc., Manassas, USA tthosanimicron.com Andres Prado Esp…

基于 HT for Web 的轻量化 3D 数字孪生数据中心解决方案

一、技术架构&#xff1a;HT for Web 的核心能力 图扑软件自主研发的 HT for Web 是基于 HTML5 的 2D/3D 可视化引擎&#xff0c;核心技术特性包括&#xff1a; 跨平台渲染&#xff1a;采用 WebGL 技术&#xff0c;支持 PC、移动端浏览器直接访问&#xff0c;兼容主流操作系统…

JavaScript 性能优化:从入门到实战

在当今快节奏的互联网时代&#xff0c;用户对网页和应用的加载速度与响应性能要求越来越高。JavaScript 作为网页交互的核心语言&#xff0c;其性能表现直接影响用户体验。本文将用简单易懂的语言&#xff0c;带你了解 JavaScript 性能优化的实用技巧&#xff0c;帮助你的代码跑…

启动metastore时报错MetaException(message:Version information not found in metastore

把hdfs清空重新安装了一下&#xff0c;hive的mysql元数据库删除掉之后重建之后一直启动报错 metastore.RetryingHMSHandler (RetryingHMSHandler.java:<init>(83)) - HMSHandler Fatal error: MetaException(message:Version information not found in metastore.) 后来…

MyBatisPlus(1):快速入门

我们知道&#xff0c;MyBatis是一个优秀的操作数据库的持久层框架&#xff08;优秀持久层框架——MyBatis&#xff09;&#xff0c;其基于底层的JDBC进行高度封装&#xff0c;极大的简化了开发。但是对于单表操作而言&#xff0c;我们需要重复地编写简单的CRUD语句。这其实是不…

京东热点缓存探测系统JDhotkey架构剖析

热点探测使用场景 MySQL 中被频繁访问的数据 &#xff0c;如热门商品的主键 IdRedis 缓存中被密集访问的 Key&#xff0c;如热门商品的详情需要 get goods$Id恶意攻击或机器人爬虫的请求信息&#xff0c;如特定标识的 userId、机器 IP频繁被访问的接口地址&#xff0c;如获取用…

【Elasticsearch】ILM(Index Lifecycle Management)策略详解

ILM&#xff08;Index Lifecycle Management&#xff09;策略详解 1.什么是 ILM 策略&#xff1f;2.ILM 解决的核心业务问题3.ILM 生命周期阶段3.1 Hot&#xff08;热阶段&#xff09;3.2 Warm&#xff08;温阶段&#xff09;3.3 Cold&#xff08;冷阶段&#xff09;3.4 Delete…

linux 后记

Linux Server 下载一个Server的版本&#xff0c;就是那种只有命令行的 学会这个就可以去租一个aliyun服务器&#xff0c;挺便宜的 如果在aliyun买服务器的话就不用管镜像源 但是如果是自己的虚拟机就必须设置镜像源&#xff0c;上网搜索阿里的镜像源&#xff0c;然后手动输入&…

【笔记】在 MSYS2 MINGW64 环境中安装构建工具链(CMake、GCC、Make)

&#x1f4dd; 在 MSYS2 MINGW64 环境中安装构建工具链&#xff08;CMake、GCC、Make&#xff09; ✅ 目标说明 记录在 MSYS2 的 MINGW64 工具链环境中&#xff0c;成功安装用于 C/C 构建的常用开发工具。 包括&#xff1a; GCC 编译器Make 构建系统CMake 跨平台构建工具基础开…

PyTorch -TensorBoard的使用 (一)

设置环境 新建python文件 .py 安装Tensorboard 在终端进行安装 显示安装成功 两个logs&#xff0c;出现这种情况怎么解决 所有的logs文件删掉delete&#xff0c;重新运行 add_image 不满足要求 Opencv-numpy 安装Opencv add_image 用法示例 &#xff08;500&#xff0c;375&am…

Redis最佳实践——性能优化技巧之数据结构选择

Redis在电商应用中的数据结构选择与性能优化技巧 一、电商核心场景与数据结构选型矩阵 应用场景推荐数据结构内存占用读写复杂度典型操作商品详情缓存Hash低O(1)HGETALL, HMSET购物车管理Hash中O(1)HINCRBY, HDEL用户会话管理Hash低O(1)HSETEX, HGET商品分类目录Sorted Set高O…

网络安全方向在校生有哪些证书适合考取?

工作7年得出结论&#xff1a;网络安全&#xff0c;考任何证书都没有用&#xff0c;实力才是根本。我是2021年考的 CISSP&#xff0c;报了培训班&#xff0c;花了1万一千块钱&#xff0c;签的保障班还是服务班不记得了&#xff0c;大概意思就是你放心去考&#xff0c;考不过可以…

从0开始学习R语言--Day14--贝叶斯统计与结构方程模型

贝叶斯统计 在很多时候&#xff0c;我们经常会看到在统计分析中出现很多反直觉的结论&#xff0c;比如假如有一种病&#xff0c;人群中的患病率为1%&#xff0c;患者真患病时&#xff0c;检测结果为阳性的概率是99%&#xff0c;如果没有&#xff0c;则检测结果为阳性的概率是5…

[Python] 如何使用 Python 调用 Dify 工作流服务实现自动化翻译

在实际项目中,自动化工作流服务可以大大简化复杂任务的处理流程。本文将介绍如何通过 Python 脚本调用 Dify 提供的工作流 API,实现文本翻译的自动化操作。该流程包括设置 API 接口、构造请求体并处理返回结果。 一、背景介绍:什么是 Dify 工作流服务? Dify 是一款支持多种…

PTA-根据已有类Worker,使用LinkedList编写一个WorkerList类,实现计算所有工人总工资的功能。

目录 1.问题描述 2.函数接口定义&#xff1a; 3.裁判测试程序样例&#xff1a; 4.输入和输出样例 输入样例&#xff1a; 输出样例&#xff1a; 5.实现代码 1.问题描述 Main类&#xff1a;在main方法中&#xff0c;调用constructWorkerList方法构建一个Worker对象链表…