贪心算法应用:最小反馈顶点集问题详解

在这里插入图片描述

贪心算法应用:最小反馈顶点集问题详解

1. 问题定义与背景

1.1 反馈顶点集定义

反馈顶点集(Feedback Vertex Set, FVS)是指在一个有向图中,删除该集合中的所有顶点后,图中将不再存在任何有向环。换句话说,反馈顶点集是破坏图中所有环所需删除的顶点集合。

1.2 最小反馈顶点集问题

最小反馈顶点集问题是指在一个给定的有向图中,寻找一个最小的反馈顶点集,即包含顶点数量最少的反馈顶点集。这是一个经典的NP难问题,在实际应用中有着广泛的需求。

1.3 应用场景

  • 死锁检测与预防:在操作系统中识别和打破进程间的循环等待
  • 电路设计:避免逻辑电路中的反馈循环
  • 生物信息学:分析基因调控网络
  • 软件工程:分析程序控制流图中的循环结构

2. 贪心算法原理

2.1 贪心算法基本思想

贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致结果是全局最优的算法策略。对于最小反馈顶点集问题,贪心算法的基本思路是:

  1. 识别图中最有可能破坏多个环的顶点
  2. 将该顶点加入反馈顶点集
  3. 从图中移除该顶点及其相关边
  4. 重复上述过程直到图中不再有环

2.2 贪心策略选择

常见的贪心策略包括:

  • 最大度数优先:选择当前图中度数最大的顶点
  • 最大环参与度:选择参与最多环的顶点
  • 权重策略:在有顶点权重的情况下,选择权重与度数比最优的顶点

3. Java实现详细解析

3.1 图的数据结构表示

我们首先需要定义图的表示方式。在Java中,可以使用邻接表来表示有向图。

import java.util.*;public class DirectedGraph {private Map<Integer, List<Integer>> adjacencyList;private Set<Integer> vertices;public DirectedGraph() {this.adjacencyList = new HashMap<>();this.vertices = new HashSet<>();}public void addVertex(int vertex) {vertices.add(vertex);adjacencyList.putIfAbsent(vertex, new ArrayList<>());}public void addEdge(int from, int to) {addVertex(from);addVertex(to);adjacencyList.get(from).add(to);}public List<Integer> getNeighbors(int vertex) {return adjacencyList.getOrDefault(vertex, new ArrayList<>());}public Set<Integer> getVertices() {return new HashSet<>(vertices);}public DirectedGraph copy() {DirectedGraph copy = new DirectedGraph();for (int v : vertices) {for (int neighbor : adjacencyList.get(v)) {copy.addEdge(v, neighbor);}}return copy;}public void removeVertex(int vertex) {vertices.remove(vertex);adjacencyList.remove(vertex);for (List<Integer> neighbors : adjacencyList.values()) {neighbors.removeIf(v -> v == vertex);}}
}

3.2 环检测实现

在实现贪心算法前,我们需要能够检测图中是否存在环。这里使用深度优先搜索(DFS)来实现环检测。

public boolean hasCycle() {Set<Integer> visited = new HashSet<>();Set<Integer> recursionStack = new HashSet<>();for (int vertex : vertices) {if (!visited.contains(vertex) && hasCycleUtil(vertex, visited, recursionStack)) {return true;}}return false;
}private boolean hasCycleUtil(int vertex, Set<Integer> visited, Set<Integer> recursionStack) {visited.add(vertex);recursionStack.add(vertex);for (int neighbor : adjacencyList.getOrDefault(vertex, new ArrayList<>())) {if (!visited.contains(neighbor)) {if (hasCycleUtil(neighbor, visited, recursionStack)) {return true;}} else if (recursionStack.contains(neighbor)) {return true;}}recursionStack.remove(vertex);return false;
}

3.3 贪心算法实现

基于最大度数优先策略的贪心算法实现:

public Set<Integer> greedyFVS() {Set<Integer> fvs = new HashSet<>();DirectedGraph graphCopy = this.copy();while (graphCopy.hasCycle()) {// 选择当前图中度数最大的顶点int vertexToRemove = selectVertexWithMaxDegree(graphCopy);// 添加到反馈顶点集fvs.add(vertexToRemove);// 从图中移除该顶点graphCopy.removeVertex(vertexToRemove);}return fvs;
}private int selectVertexWithMaxDegree(DirectedGraph graph) {int maxDegree = -1;int selectedVertex = -1;for (int vertex : graph.getVertices()) {int outDegree = graph.getNeighbors(vertex).size();int inDegree = 0;// 计算入度for (int v : graph.getVertices()) {if (graph.getNeighbors(v).contains(vertex)) {inDegree++;}}int totalDegree = outDegree + inDegree;if (totalDegree > maxDegree) {maxDegree = totalDegree;selectedVertex = vertex;}}return selectedVertex;
}

3.4 改进的贪心策略实现

更复杂的贪心策略可以考虑顶点参与环的数量:

public Set<Integer> improvedGreedyFVS() {Set<Integer> fvs = new HashSet<>();DirectedGraph graphCopy = this.copy();while (graphCopy.hasCycle()) {// 选择参与最多环的顶点int vertexToRemove = selectVertexInMostCycles(graphCopy);fvs.add(vertexToRemove);graphCopy.removeVertex(vertexToRemove);}return fvs;
}private int selectVertexInMostCycles(DirectedGraph graph) {Map<Integer, Integer> cycleCount = new HashMap<>();// 初始化所有顶点的环计数for (int vertex : graph.getVertices()) {cycleCount.put(vertex, 0);}// 使用DFS检测环并计数for (int vertex : graph.getVertices()) {Set<Integer> visited = new HashSet<>();Stack<Integer> path = new Stack<>();countCyclesUtil(graph, vertex, visited, path, cycleCount);}// 选择参与最多环的顶点return Collections.max(cycleCount.entrySet(), Map.Entry.comparingByValue()).getKey();
}private void countCyclesUtil(DirectedGraph graph, int vertex, Set<Integer> visited, Stack<Integer> path, Map<Integer, Integer> cycleCount) {if (path.contains(vertex)) {// 发现环,增加路径上所有顶点的计数int index = path.indexOf(vertex);for (int i = index; i < path.size(); i++) {int v = path.get(i);cycleCount.put(v, cycleCount.get(v) + 1);}return;}if (visited.contains(vertex)) {return;}visited.add(vertex);path.push(vertex);for (int neighbor : graph.getNeighbors(vertex)) {countCyclesUtil(graph, neighbor, visited, path, cycleCount);}path.pop();
}

4. 算法分析与优化

4.1 时间复杂度分析

  • 基本贪心算法:

    • 每次环检测:O(V+E)
    • 每次选择顶点:O(V^2)(因为要计算每个顶点的度数)
    • 最坏情况下需要移除O(V)个顶点
    • 总时间复杂度:O(V^3 + V*E)
  • 改进的贪心算法:

    • 环计数实现较为复杂,最坏情况下为指数时间
    • 实际应用中通常需要限制DFS的深度或使用近似方法

4.2 近似比分析

贪心算法提供的是一种近似解法。对于最小反馈顶点集问题:

  • 基本贪心算法的近似比为O(log n log log n)
  • 更复杂的贪心策略可以达到O(log n)近似比
  • 在特殊类型的图中可能有更好的近似比

4.3 优化策略

  1. 局部搜索优化:在贪心算法得到的解基础上进行局部优化
  2. 混合策略:结合多种贪心策略,选择最优解
  3. 并行计算:并行计算各顶点的环参与度
  4. 启发式剪枝:限制DFS深度或使用随机游走估计环参与度

5. 完整Java实现示例

import java.util.*;
import java.util.stream.Collectors;public class FeedbackVertexSet {public static void main(String[] args) {// 创建示例图DirectedGraph graph = new DirectedGraph();graph.addEdge(1, 2);graph.addEdge(2, 3);graph.addEdge(3, 4);graph.addEdge(4, 1); // 形成环1-2-3-4-1graph.addEdge(2, 5);graph.addEdge(5, 6);graph.addEdge(6, 2); // 形成环2-5-6-2graph.addEdge(7, 8);graph.addEdge(8, 7); // 形成环7-8-7System.out.println("原始图是否有环: " + graph.hasCycle());// 使用基本贪心算法Set<Integer> basicFVS = graph.greedyFVS();System.out.println("基本贪心算法找到的FVS: " + basicFVS);System.out.println("大小: " + basicFVS.size());// 使用改进贪心算法Set<Integer> improvedFVS = graph.improvedGreedyFVS();System.out.println("改进贪心算法找到的FVS: " + improvedFVS);System.out.println("大小: " + improvedFVS.size());// 验证解的正确性DirectedGraph testGraph = graph.copy();for (int v : improvedFVS) {testGraph.removeVertex(v);}System.out.println("移除FVS后图是否有环: " + testGraph.hasCycle());}
}class DirectedGraph {// ... 前面的图实现代码 ...// 添加一个更高效的贪心算法实现public Set<Integer> efficientGreedyFVS() {Set<Integer> fvs = new HashSet<>();DirectedGraph graphCopy = this.copy();// 使用优先队列来高效获取最大度数顶点PriorityQueue<Map.Entry<Integer, Integer>> maxHeap = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());// 初始化度数表Map<Integer, Integer> degreeMap = new HashMap<>();for (int v : graphCopy.getVertices()) {int degree = graphCopy.getNeighbors(v).size();// 计算入度int inDegree = 0;for (int u : graphCopy.getVertices()) {if (graphCopy.getNeighbors(u).contains(v)) {inDegree++;}}degreeMap.put(v, degree + inDegree);}maxHeap.addAll(degreeMap.entrySet());while (graphCopy.hasCycle()) {if (maxHeap.isEmpty()) break;Map.Entry<Integer, Integer> entry = maxHeap.poll();int vertex = entry.getKey();int currentDegree = degreeMap.getOrDefault(vertex, 0);// 检查度数是否最新(因为图可能已经改变)int actualDegree = graphCopy.getNeighbors(vertex).size();int actualInDegree = 0;for (int u : graphCopy.getVertices()) {if (graphCopy.getNeighbors(u).contains(vertex)) {actualInDegree++;}}int totalDegree = actualDegree + actualInDegree;if (totalDegree < currentDegree) {// 度数已变化,重新插入entry.setValue(totalDegree);maxHeap.add(entry);continue;}// 添加到FVSfvs.add(vertex);// 更新邻居的度数for (int neighbor : graphCopy.getNeighbors(vertex)) {if (degreeMap.containsKey(neighbor)) {degreeMap.put(neighbor, degreeMap.get(neighbor) - 1);}}// 更新指向该顶点的邻居for (int u : graphCopy.getVertices()) {if (graphCopy.getNeighbors(u).contains(vertex)) {if (degreeMap.containsKey(u)) {degreeMap.put(u, degreeMap.get(u) - 1);}}}// 从图中移除顶点graphCopy.removeVertex(vertex);degreeMap.remove(vertex);}return fvs;}// 添加一个基于随机游走的近似环计数方法private int selectVertexInMostCyclesApprox(DirectedGraph graph, int walks, int steps) {Map<Integer, Integer> cycleCount = new HashMap<>();Random random = new Random();List<Integer> vertices = new ArrayList<>(graph.getVertices());for (int v : graph.getVertices()) {cycleCount.put(v, 0);}for (int i = 0; i < walks; i++) {int startVertex = vertices.get(random.nextInt(vertices.size()));int currentVertex = startVertex;Set<Integer> visitedInWalk = new HashSet<>();List<Integer> path = new ArrayList<>();for (int step = 0; step < steps; step++) {List<Integer> neighbors = graph.getNeighbors(currentVertex);if (neighbors.isEmpty()) break;int nextVertex = neighbors.get(random.nextInt(neighbors.size()));if (path.contains(nextVertex)) {// 发现环int index = path.indexOf(nextVertex);for (int j = index; j < path.size(); j++) {int v = path.get(j);cycleCount.put(v, cycleCount.get(v) + 1);}break;}path.add(nextVertex);currentVertex = nextVertex;}}return Collections.max(cycleCount.entrySet(), Map.Entry.comparingByValue()).getKey();}
}

6. 测试与验证

6.1 测试用例设计

为了验证算法的正确性和效率,我们需要设计多种测试用例:

  1. 简单环图:单个环或多个不相交的环
  2. 复杂环图:多个相交的环
  3. 无环图:验证算法不会返回不必要的顶点
  4. 完全图:所有顶点之间都有边
  5. 随机图:随机生成的有向图

6.2 验证方法

  1. 移除返回的反馈顶点集后,检查图中是否确实无环
  2. 比较不同算法得到的解的大小
  3. 测量算法运行时间

6.3 性能测试示例

public class PerformanceTest {public static void main(String[] args) {int[] sizes = {10, 50, 100, 200, 500};for (int size : sizes) {System.out.println("\n测试图大小: " + size);DirectedGraph graph = generateRandomGraph(size, size * 2);long start, end;start = System.currentTimeMillis();Set<Integer> basicFVS = graph.greedyFVS();end = System.currentTimeMillis();System.out.printf("基本贪心算法: %d 顶点, 耗时 %d ms%n", basicFVS.size(), end - start);start = System.currentTimeMillis();Set<Integer> efficientFVS = graph.efficientGreedyFVS();end = System.currentTimeMillis();System.out.printf("高效贪心算法: %d 顶点, 耗时 %d ms%n", efficientFVS.size(), end - start);// 对于大图,改进算法可能太慢,可以跳过if (size <= 100) {start = System.currentTimeMillis();Set<Integer> improvedFVS = graph.improvedGreedyFVS();end = System.currentTimeMillis();System.out.printf("改进贪心算法: %d 顶点, 耗时 %d ms%n", improvedFVS.size(), end - start);}}}private static DirectedGraph generateRandomGraph(int vertexCount, int edgeCount) {DirectedGraph graph = new DirectedGraph();Random random = new Random();for (int i = 0; i < vertexCount; i++) {graph.addVertex(i);}for (int i = 0; i < edgeCount; i++) {int from = random.nextInt(vertexCount);int to = random.nextInt(vertexCount);if (from != to) {graph.addEdge(from, to);}}return graph;}
}

7. 实际应用与扩展

7.1 加权反馈顶点集

在实际应用中,顶点可能有不同的权重,我们需要寻找权重和最小的反馈顶点集:

public Set<Integer> weightedGreedyFVS(Map<Integer, Integer> vertexWeights) {Set<Integer> fvs = new HashSet<>();DirectedGraph graphCopy = this.copy();while (graphCopy.hasCycle()) {// 选择(度数/权重)最大的顶点int vertexToRemove = -1;double maxRatio = -1;for (int vertex : graphCopy.getVertices()) {int outDegree = graphCopy.getNeighbors(vertex).size();int inDegree = 0;for (int v : graphCopy.getVertices()) {if (graphCopy.getNeighbors(v).contains(vertex)) {inDegree++;}}double ratio = (outDegree + inDegree) / (double) vertexWeights.get(vertex);if (ratio > maxRatio) {maxRatio = ratio;vertexToRemove = vertex;}}fvs.add(vertexToRemove);graphCopy.removeVertex(vertexToRemove);}return fvs;
}

7.2 并行化实现

对于大型图,可以并行计算各顶点的环参与度:

public Set<Integer> parallelGreedyFVS() {Set<Integer> fvs = new HashSet<>();DirectedGraph graphCopy = this.copy();ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());while (graphCopy.hasCycle()) {List<Future<VertexCycleCount>> futures = new ArrayList<>();for (int vertex : graphCopy.getVertices()) {futures.add(executor.submit(() -> {int count = countCyclesForVertex(graphCopy, vertex);return new VertexCycleCount(vertex, count);}));}VertexCycleCount best = new VertexCycleCount(-1, -1);for (Future<VertexCycleCount> future : futures) {try {VertexCycleCount current = future.get();if (current.count > best.count) {best = current;}} catch (Exception e) {e.printStackTrace();}}if (best.vertex != -1) {fvs.add(best.vertex);graphCopy.removeVertex(best.vertex);}}executor.shutdown();return fvs;
}private static class VertexCycleCount {int vertex;int count;VertexCycleCount(int vertex, int count) {this.vertex = vertex;this.count = count;}
}private int countCyclesForVertex(DirectedGraph graph, int vertex) {// 简化的环计数实现int count = 0;Set<Integer> visited = new HashSet<>();Stack<Integer> path = new Stack<>();return countCyclesUtil(graph, vertex, visited, path);
}private int countCyclesUtil(DirectedGraph graph, int vertex, Set<Integer> visited, Stack<Integer> path) {if (path.contains(vertex)) {return 1;}if (visited.contains(vertex)) {return 0;}visited.add(vertex);path.push(vertex);int total = 0;for (int neighbor : graph.getNeighbors(vertex)) {total += countCyclesUtil(graph, neighbor, visited, path);}path.pop();return total;
}

8. 总结

最小反馈顶点集问题是一个具有挑战性的NP难问题,贪心算法提供了一种有效的近似解决方案。本文详细介绍了:

  1. 问题的定义和应用背景
  2. 贪心算法的基本原理和多种策略
  3. 完整的Java实现,包括基础和改进版本
  4. 时间复杂度分析和优化策略
  5. 测试验证方法和性能考虑
  6. 实际应用扩展和并行化实现

贪心算法虽然不能保证得到最优解,但在实际应用中通常能提供令人满意的近似解,特别是在处理大规模图数据时。通过选择合适的贪心策略和优化技巧,可以在解的质量和计算效率之间取得良好的平衡。

对于需要更高精度解的场景,可以考虑将贪心算法与其他技术如分支限界、动态规划或元启发式算法结合使用。

更多资源:

https://www.kdocs.cn/l/cvk0eoGYucWA

本文发表于【纪元A梦】!

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

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

相关文章

BiliNote部署实践

​ 开源地址&#xff1a; https://github.com/JefferyHcool/BiliNote &#x1f680; 快速开始 1. 克隆仓库 git clone https://github.com/JefferyHcool/BiliNote.git cd BiliNote mv .env.example .env2. 启动后端&#xff08;FastAPI&#xff09; cd backend pip insta…

用go从零构建写一个RPC(4)--gonet网络框架重构+聚集发包

在追求高性能的分布式系统中&#xff0c;RPC 框架的底层网络能力和数据传输效率起着决定性作用。经过几轮迭代优化&#xff0c;我完成了第四版本的 RPC 框架。相比以往版本&#xff0c;这一版本的最大亮点在于 重写了底层网络框架 和 实现了发送端的数据聚集机制&#xff0c;这…

MySQL 高可用基石 - 复制监控与常见 HA 方案

MySQL 高可用基石 - 复制监控与常见 HA 方案 MySQL 复制核心原理 MySQL 复制允许数据从一个 MySQL 数据库服务器(称为主库 - Primary,旧称 Master)复制到一个或多个其他的 MySQL 服务器(称为从库 - Replica,旧称 Slave)。 复制的主要目的: 高可用性 (High Availability…

微信小程序(uniapp)自定义 TabBar

微信小程序&#xff08;uniapp&#xff09;自定义 TabBar 实现指南 在微信小程序开发中&#xff0c;TabBar 是底部导航栏的重要组件&#xff0c;但官方提供的 TabBar 样式和功能较为基础&#xff0c;无法满足所有项目的需求。本文将详细介绍如何在 uniapp 中实现自定义 TabBar…

MLP实战二:MLP 实现图像数字多分类

任务 实战&#xff08;二&#xff09;&#xff1a;MLP 实现图像多分类 基于 mnist 数据集&#xff0c;建立 mlp 模型&#xff0c;实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入&#xff0c;可视化图形数字&#xff1b; 2、完成数据预处理&#xff1a;图像数据维度转换与…

BUUCTF[HCTF 2018]WarmUp 1题解

BUUCTF[HCTF 2018]WarmUp 1题解 分析解题过程代码审计主体函数CHECK函数&#xff1a; 构造payload 总结 分析 启动靶机&#xff0c;进入网址&#xff0c;是一张滑稽的表情包&#xff1a; 程序化F12查看源码&#xff1a; 发现注释内容&#xff0c;访问 url:/source.php得到…

大陆4D毫米波雷达ARS548调试

本文介绍了大陆ARS548毫米波雷达的调试与测试流程&#xff0c;主要包括以下内容&#xff1a; 设备参数&#xff1a;最大检测距离301m&#xff08;可调93-1514m&#xff09;&#xff0c;支持gPTP时间同步。 接线调试&#xff1a; Windows需使用USB-RJ45转换器 Linux可直接连接网…

TDengine 的 AI 应用实战——运维异常检测

作者&#xff1a; derekchen Demo数据集准备 我们使用公开的 NAB数据集 里亚马逊 AWS 东海岸数据中心一次 API 网关故障中&#xff0c;某个服务器上的 CPU 使用率数据。数据的频率为 5min&#xff0c;单位为占用率。由于 API 网关的故障&#xff0c;会导致服务器上的相关应用…

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…

《一生一芯》数字实验三:加法器与ALU

1. 实验目标 设计一个能实现如下功能的4位带符号位的 补码 ALU&#xff1a; Table 4 ALU 功能列表  功能选择 功能 操作 000 加法 AB 001 减法 A-B 010 取反 Not A 011 与 A and B 100 或 A or B 101 异或 A xor B 110 比较大小 If A<B then out1…

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…

Java并发编程实战 Day 10:原子操作类详解

【Java并发编程实战 Day 10】原子操作类详解 开篇 这是“Java并发编程实战”系列的第10天&#xff0c;我们将深入探讨原子操作类的核心技术——CAS原理、ABA问题以及原子类的实现机制。通过理论结合代码实践的方式&#xff0c;帮助读者理解并掌握如何在实际工作中高效使用原子…

瀚文机械键盘固件开发详解:HWKeyboard.h文件解析与应用

【手把手教程】从零开始的机械键盘固件开发&#xff1a;HWKeyboard.h详解 前言 大家好&#xff0c;我是键盘DIY爱好者Despacito0o&#xff01;今天想和大家分享我开发的机械键盘固件核心头文件HWKeyboard.h的设计思路和技术要点。这个项目是我多年来对键盘固件研究的心血结晶…

2048游戏的技术实现分析-完全Java和Processing版

目录 简介Processing库基础项目构建指南项目结构核心数据结构游戏核心机制图形界面实现性能优化代码详解设计模式分析测试策略总结与展望简介 2048是一款由Gabriele Cirulli开发的经典益智游戏。本文将深入分析其Java实现版本的技术细节。该实现使用了Processing库来创建图形界…

Spring Boot + Elasticsearch + HBase 构建海量数据搜索系统

Spring Boot Elasticsearch HBase 构建海量数据搜索系统 &#x1f4d6; 目录 1. 系统需求分析2. 系统架构设计3. Elasticsearch 与 HBase 集成方案4. Spring Boot 项目实现5. 大规模搜索系统最佳实践 项目概述 本文档提供了基于 Spring Boot、Elasticsearch 和 HBase 构建…

【iOS】YYModel源码解析

YYModel源码解析 文章目录 YYModel源码解析前言YYModel性能优势YYModel简介YYClassInfo解析YYClassIvarInfo && objc_ivarYYClassMethodInfo && objc_methodYYClassPropertyInfo && property_tYYClassInfo && objc_class YYClassInfo的初始化细…

宇树科技更名“股份有限公司”深度解析:机器人企业IPO前奏与资本化路径

从技术落地到资本跃迁&#xff0c;拆解股改背后的上市逻辑与行业启示 核心事件&#xff1a;股改释放的上市信号 2025年5月28日&#xff0c;杭州宇树科技有限公司正式更名“杭州宇树科技股份有限公司”&#xff0c;市场主体类型变更为“股份有限公司”。尽管官方称为常规运营调…

Android Native 内存泄漏检测全解析:从原理到工具的深度实践

引言 Android应用的内存泄漏不仅发生在Java/Kotlin层&#xff0c;Native&#xff08;C/C&#xff09;层的泄漏同样普遍且隐蔽。由于Native内存不受Java虚拟机&#xff08;JVM&#xff09;管理&#xff0c;泄漏的内存无法通过GC自动回收&#xff0c;长期积累会导致应用内存占用…

Vortex GPGPU的github流程跑通与功能模块波形探索(四)

文章目录 前言一、demo的输入文件二、trace_csv三、2个值得注意的点3.1 csv指令表格里面的tmask&#xff1f;3.2 rtlsim和simx的log文件&#xff1f; 总结 前言 跟着前面那篇最后留下的几个问题接着把输出波形文件和csv文件的输入、输出搞明白&#xff01; 一、demo的输入文件…

UnityPSD文件转UI插件Psd2UnityuGUIPro3.4.0u2017.4.2介绍:Unity UI设计的高效助手

UnityPSD文件转UI插件Psd2UnityuGUIPro3.4.0u2017.4.2介绍&#xff1a;Unity UI设计的高效助手 【下载地址】UnityPSD文件转UI插件Psd2UnityuGUIPro3.4.0u2017.4.2介绍 这款开源插件将PSD文件无缝转换为Unity的UI元素&#xff0c;极大提升开发效率。它支持一键转换&#xff0c;…