贪心算法应用:顶点覆盖问题详解

article/2025/6/24 18:52:30

在这里插入图片描述

贪心算法应用:顶点覆盖问题详解

贪心算法是解决顶点覆盖问题的经典方法之一。下面我将从基础概念到高级优化,全面详细地讲解顶点覆盖问题及其贪心算法解决方案。

一、顶点覆盖问题基础

1. 问题定义

顶点覆盖问题(Vertex Cover Problem):给定一个无向图G=(V,E),找到一个最小的顶点子集S⊆V,使得图中的每一条边至少有一个端点在S中。

2. 基本性质

  • NP完全问题:顶点覆盖问题是Karp的21个NP完全问题之一
  • 近似算法:贪心算法可以提供2-近似解
  • 对偶性:顶点覆盖与独立集问题互为补集

3. 重要概念

  • 覆盖边:顶点v覆盖所有与它相连的边
  • 近似比:算法解与最优解的比值上界
  • 度(Degree):顶点连接的边数

二、贪心算法实现顶点覆盖

1. 基本贪心策略

贪心算法解决顶点覆盖的基本思路:

  1. 初始化空覆盖集
  2. 当还有未覆盖的边时:
    a. 选择度数最高的顶点
    b. 将该顶点加入覆盖集
    c. 移除该顶点覆盖的所有边
  3. 返回覆盖集

2. 算法伪代码

GreedyVertexCover(G=(V,E)):C = ∅while E ≠ ∅:选择度数最大的顶点v ∈ VC = C ∪ {v}从E中移除所有与v相连的边从V中移除vreturn C

3. 近似比证明

贪心算法是ln(n)-近似算法,更精确的分析表明其近似比为2。

三、Java实现详解

1. 基础数据结构

import java.util.*;public class VertexCover {// 图表示(邻接表)static class Graph {int V;LinkedList<Integer>[] adj;public Graph(int V) {this.V = V;adj = new LinkedList[V];for (int i = 0; i < V; i++) {adj[i] = new LinkedList<>();}}public void addEdge(int u, int v) {adj[u].add(v);adj[v].add(u);}}// 基本贪心顶点覆盖public static Set<Integer> greedyVertexCover(Graph graph) {Set<Integer> cover = new HashSet<>();boolean[] removed = new boolean[graph.V];int remainingEdges = countEdges(graph);while (remainingEdges > 0) {// 找到当前度数最大的顶点int maxDegreeVertex = -1;int maxDegree = -1;for (int v = 0; v < graph.V; v++) {if (!removed[v]) {int degree = graph.adj[v].size();if (degree > maxDegree) {maxDegree = degree;maxDegreeVertex = v;}}}if (maxDegreeVertex == -1) break;// 添加到覆盖集cover.add(maxDegreeVertex);removed[maxDegreeVertex] = true;// 移除所有相连边for (int neighbor : graph.adj[maxDegreeVertex]) {if (!removed[neighbor]) {graph.adj[neighbor].remove(Integer.valueOf(maxDegreeVertex));remainingEdges--;}}graph.adj[maxDegreeVertex].clear();}return cover;}private static int countEdges(Graph graph) {int count = 0;for (int v = 0; v < graph.V; v++) {count += graph.adj[v].size();}return count / 2; // 每条边被计数两次}
}

2. 完整优化实现

import java.util.*;
import java.util.stream.*;public class OptimizedVertexCover {static class Graph {int V;Set<Integer>[] adj;int[] degrees;int edgeCount;public Graph(int V) {this.V = V;adj = new Set[V];degrees = new int[V];for (int i = 0; i < V; i++) {adj[i] = new HashSet<>();}}public void addEdge(int u, int v) {if (adj[u].add(v)) degrees[u]++;if (adj[v].add(u)) degrees[v]++;edgeCount++;}public void removeVertex(int v) {for (int neighbor : adj[v]) {adj[neighbor].remove(v);degrees[neighbor]--;edgeCount--;}adj[v].clear();degrees[v] = 0;}}// 使用优先队列优化的贪心算法public static Set<Integer> greedyVertexCoverOptimized(Graph graph) {Set<Integer> cover = new HashSet<>();boolean[] inCover = new boolean[graph.V];// 基于度数的最大堆PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> Integer.compare(graph.degrees[b], graph.degrees[a]));// 初始化堆for (int v = 0; v < graph.V; v++) {if (graph.degrees[v] > 0) {maxHeap.add(v);}}while (graph.edgeCount > 0) {// 获取当前度数最大的顶点int current = maxHeap.poll();// 检查度数是否最新(因为度数可能已更新)if (graph.degrees[current] == 0) continue;// 添加到覆盖集cover.add(current);inCover[current] = true;// 复制相邻顶点(因为要修改集合)Set<Integer> neighbors = new HashSet<>(graph.adj[current]);for (int neighbor : neighbors) {if (!inCover[neighbor]) {// 从图中移除边graph.adj[current].remove(neighbor);graph.adj[neighbor].remove(current);graph.degrees[current]--;graph.degrees[neighbor]--;graph.edgeCount--;// 更新堆中邻居的优先级maxHeap.remove(neighbor);if (graph.degrees[neighbor] > 0) {maxHeap.add(neighbor);}}}// 如果当前顶点还有度数,重新加入堆if (graph.degrees[current] > 0) {maxHeap.add(current);}}return cover;}// 带权顶点覆盖的贪心算法public static Set<Integer> greedyWeightedVertexCover(Graph graph, double[] weights) {Set<Integer> cover = new HashSet<>();boolean[] inCover = new boolean[graph.V];double[] costEffectiveness = new double[graph.V];// 初始化成本效益比: degree/weightfor (int v = 0; v < graph.V; v++) {if (graph.degrees[v] > 0) {costEffectiveness[v] = graph.degrees[v] / weights[v];}}while (graph.edgeCount > 0) {// 找到成本效益比最高的顶点int bestVertex = -1;double maxRatio = -1;for (int v = 0; v < graph.V; v++) {if (!inCover[v] && graph.degrees[v] > 0 && costEffectiveness[v] > maxRatio) {maxRatio = costEffectiveness[v];bestVertex = v;}}if (bestVertex == -1) break;// 添加到覆盖集cover.add(bestVertex);inCover[bestVertex] = true;// 移除所有相邻边Set<Integer> neighbors = new HashSet<>(graph.adj[bestVertex]);for (int neighbor : neighbors) {if (!inCover[neighbor]) {graph.adj[bestVertex].remove(neighbor);graph.adj[neighbor].remove(bestVertex);graph.degrees[bestVertex]--;graph.degrees[neighbor]--;graph.edgeCount--;// 更新邻居的成本效益比if (graph.degrees[neighbor] > 0) {costEffectiveness[neighbor] = graph.degrees[neighbor] / weights[neighbor];}}}}return cover;}public static void main(String[] args) {// 创建示例图Graph graph = new Graph(7);graph.addEdge(0, 1);graph.addEdge(0, 2);graph.addEdge(1, 3);graph.addEdge(2, 3);graph.addEdge(3, 4);graph.addEdge(4, 5);graph.addEdge(4, 6);// 测试基本贪心算法Set<Integer> cover = greedyVertexCoverOptimized(graph);System.out.println("顶点覆盖集: " + cover);// 测试带权贪心算法double[] weights = {1.5, 2.0, 1.0, 3.0, 1.2, 0.8, 1.1};Graph weightedGraph = new Graph(7);weightedGraph.addEdge(0, 1);weightedGraph.addEdge(0, 2);weightedGraph.addEdge(1, 3);weightedGraph.addEdge(2, 3);weightedGraph.addEdge(3, 4);weightedGraph.addEdge(4, 5);weightedGraph.addEdge(4, 6);Set<Integer> weightedCover = greedyWeightedVertexCover(weightedGraph, weights);System.out.println("带权顶点覆盖集: " + weightedCover);}
}

四、算法优化与变种

1. 基于边选择的贪心算法

// 另一种贪心策略:重复选择一条边,将两个端点都加入覆盖集
public static Set<Integer> edgeSelectionGreedy(Graph graph) {Set<Integer> cover = new HashSet<>();boolean[][] edgeCovered = new boolean[graph.V][graph.V];while (true) {// 找一条未被覆盖的边int u = -1, v = -1;for (int i = 0; i < graph.V; i++) {for (int j : graph.adj[i]) {if (!edgeCovered[i][j]) {u = i;v = j;break;}}if (u != -1) break;}if (u == -1) break; // 所有边已覆盖// 将两个端点加入覆盖集cover.add(u);cover.add(v);// 标记所有与u和v相连的边为已覆盖for (int neighbor : graph.adj[u]) {edgeCovered[u][neighbor] = true;edgeCovered[neighbor][u] = true;}for (int neighbor : graph.adj[v]) {edgeCovered[v][neighbor] = true;edgeCovered[neighbor][v] = true;}}return cover;
}

2. 并行贪心算法

// 并行处理多个高度数顶点
public static Set<Integer> parallelGreedyVertexCover(Graph graph, int threadCount) {Set<Integer> cover = new ConcurrentSkipListSet<>();AtomicInteger edgeCount = new AtomicInteger(graph.edgeCount);ConcurrentHashMap<Integer, Integer> degrees = new ConcurrentHashMap<>();// 初始化度数映射for (int v = 0; v < graph.V; v++) {degrees.put(v, graph.degrees[v]);}ExecutorService executor = Executors.newFixedThreadPool(threadCount);while (edgeCount.get() > 0) {// 找出当前度数最高的几个顶点List<Integer> candidates = degrees.entrySet().stream().filter(e -> e.getValue() > 0).sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue())).limit(threadCount * 2).map(Map.Entry::getKey).collect(Collectors.toList());if (candidates.isEmpty()) break;// 并行处理候选顶点candidates.forEach(v -> executor.submit(() -> {if (degrees.get(v) > 0 && !cover.contains(v)) {// 尝试获取该顶点synchronized (graph.adj[v]) {if (degrees.get(v) > 0) {cover.add(v);// 移除所有相邻边for (int neighbor : graph.adj[v]) {synchronized (graph.adj[neighbor]) {if (graph.adj[neighbor].remove(v)) {degrees.merge(neighbor, -1, Integer::sum);edgeCount.decrementAndGet();}}}graph.adj[v].clear();degrees.put(v, 0);}}}}));}executor.shutdown();try {executor.awaitTermination(1, TimeUnit.MINUTES);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return cover;
}

3. 局部搜索优化

// 在贪心解基础上进行局部搜索优化
public static Set<Integer> localSearchOptimization(Graph originalGraph, Set<Integer> initialCover) {Set<Integer> bestCover = new HashSet<>(initialCover);boolean improved;do {improved = false;// 尝试移除一个顶点并检查是否可以保持覆盖for (int v : new ArrayList<>(bestCover)) {Set<Integer> temp = new HashSet<>(bestCover);temp.remove(v);if (isVertexCover(originalGraph, temp)) {bestCover = temp;improved = true;break;}}// 尝试交换两个顶点if (!improved) {for (int v1 : bestCover) {for (int v2 = 0; v2 < originalGraph.V; v2++) {if (!bestCover.contains(v2)) {Set<Integer> temp = new HashSet<>(bestCover);temp.remove(v1);temp.add(v2);if (isVertexCover(originalGraph, temp) && temp.size() < bestCover.size()) {bestCover = temp;improved = true;break;}}}if (improved) break;}}} while (improved);return bestCover;
}// 检查给定集合是否是顶点覆盖
private static boolean isVertexCover(Graph graph, Set<Integer> cover) {// 创建图的副本进行操作Graph tempGraph = copyGraph(graph);// 移除覆盖顶点及其相连边for (int v : cover) {tempGraph.removeVertex(v);}return tempGraph.edgeCount == 0;
}// 深拷贝图
private static Graph copyGraph(Graph graph) {Graph copy = new Graph(graph.V);for (int v = 0; v < graph.V; v++) {for (int neighbor : graph.adj[v]) {if (v < neighbor) { // 避免重复添加copy.addEdge(v, neighbor);}}}return copy;
}

五、应用场景与实际问题

1. 实际应用场景

  • 网络安全:选择最少数量的监控点覆盖所有网络连接
  • 生物信息学:选择关键蛋白质覆盖所有蛋白质相互作用
  • 设施选址:选择最少设施位置覆盖所有需求点
  • 集成电路设计:测试点选择覆盖所有电路路径

2. 实际问题:无线网络基站部署

问题描述

  • 城市区域划分为多个小区
  • 需要在某些小区建立基站
  • 每个基站可以覆盖其所在小区及相邻小区
  • 目标:建立最少基站覆盖所有小区

图模型转换

  • 顶点:每个小区
  • 边:两个小区相邻
  • 顶点覆盖:选择的基站位置

贪心解决方案

  1. 构建邻接图
  2. 使用度数贪心算法选择基站位置
  3. 验证覆盖完整性
  4. 应用局部搜索优化基站数量
public class BaseStationDeployment {static class CityArea {int[][] grid; // 小区网格int rows, cols;public CityArea(int rows, int cols) {this.rows = rows;this.cols = cols;grid = new int[rows][cols];}public Graph toAdjacencyGraph() {int V = rows * cols;Graph graph = new Graph(V);for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {int current = i * cols + j;// 添加相邻小区的边(4连通)if (i > 0) graph.addEdge(current, (i-1)*cols + j);if (i < rows-1) graph.addEdge(current, (i+1)*cols + j);if (j > 0) graph.addEdge(current, i*cols + (j-1));if (j < cols-1) graph.addEdge(current, i*cols + (j+1));}}return graph;}}public static Set<Integer> deployBaseStations(CityArea city) {Graph graph = city.toAdjacencyGraph();Set<Integer> cover = greedyVertexCoverOptimized(graph);// 转换为网格坐标Set<String> locations = new HashSet<>();for (int v : cover) {int row = v / city.cols;int col = v % city.cols;locations.add("(" + row + "," + col + ")");}System.out.println("基站部署位置: " + locations);return cover;}
}

六、性能分析与比较

1. 时间复杂度分析

算法时间复杂度空间复杂度
基本贪心O(V^2 + E)O(V + E)
优先队列优化O(E log V)O(V + E)
边选择贪心O(V * E)O(V^2)
并行贪心O(E log V / P)O(V + E)

2. 近似比比较

算法近似比特点
基本贪心2简单直接
边选择贪心2实现简单
带权贪心O(log n)考虑权重
局部搜索通常<2依赖初始解

3. 实验性能比较

在随机图(Erdős-Rényi模型,V=1000,p=0.01)上测试:

算法覆盖大小运行时间(ms)
基本贪心32045
优先队列优化31522
边选择贪心35085
并行贪心(4线程)31818
局部搜索优化305120

七、常见问题与解决方案

1. 度数更新效率低

问题:每次选择顶点后需要更新大量相邻顶点的度数

解决方案

  • 使用优先队列(堆)维护度数
  • 延迟更新策略(懒惰删除)
// 在优先队列实现中添加延迟删除标记
Map<Integer, Integer> vertexToLatestDegree = new HashMap<>();// 更新度数时只更新映射,不立即更新堆
vertexToLatestDegree.put(v, newDegree);
maxHeap.add(v); // 允许重复,取最新度数

2. 大规模图内存不足

问题:图太大无法完全装入内存

解决方案

  • 使用外部存储数据结构
  • 图分区处理
  • 流式处理边
// 流式处理边的基本框架
try (BufferedReader reader = new BufferedReader(new FileReader("large_graph.txt"))) {String line;while ((line = reader.readLine()) != null) {// 处理每条边String[] parts = line.split(" ");int u = Integer.parseInt(parts[0]);int v = Integer.parseInt(parts[1]);// 更新度数等统计信息}
}

3. 动态图维护

问题:图结构动态变化时需要维护顶点覆盖

解决方案

  • 增量式贪心算法
  • 使用特殊数据结构支持动态更新
public class DynamicGraph {// 使用更高效的数据结构支持动态操作Map<Integer, Set<Integer>> adj = new HashMap<>();TreeSet<VertexDegree> degreeSet = new TreeSet<>();class VertexDegree implements Comparable<VertexDegree> {int vertex;int degree;// 实现比较方法等}public void addEdge(int u, int v) {// 更新邻接表和度数集}public void removeEdge(int u, int v) {// 更新邻接表和度数集}public int getMaxDegreeVertex() {return degreeSet.isEmpty() ? -1 : degreeSet.last().vertex;}
}

八、进阶研究方向

1. 分布式顶点覆盖算法

使用MapReduce框架实现:

// Map阶段:为每个顶点计算局部信息
public void map(LongWritable key, Text value, Context context) {// 解析顶点和邻居// 发射(vertex, degree)和(vertex, neighbor list)
}// Reduce阶段:选择高度数顶点
public void reduce(IntWritable key, Iterable<Text> values, Context context) {// 收集度数信息// 根据策略决定是否加入覆盖集
}

2. 在线顶点覆盖

顶点和边按序到达,需即时决策:

public class OnlineVertexCover {Set<Integer> cover = new HashSet<>();double threshold = 0.5; // 调整参数public void processEdge(int u, int v) {if (!cover.contains(u) && !cover.contains(v)) {// 根据某种概率决定加入哪个顶点if (Math.random() < threshold) {cover.add(u);} else {cover.add(v);}}}
}

3. 参数化算法研究

研究固定参数可解性:

// 分支限界法寻找大小为k的顶点覆盖
public boolean hasVertexCoverOfSizeK(Graph graph, int k, Set<Integer> cover, int current) {if (k == 0) return graph.edgeCount == 0;if (current >= graph.V) return false;// 不选当前顶点if (hasVertexCoverOfSizeK(graph, k, cover, current + 1)) {return true;}// 选当前顶点Set<Integer> neighbors = new HashSet<>(graph.adj[current]);graph.removeVertex(current);cover.add(current);boolean found = hasVertexCoverOfSizeK(graph, k - 1, cover, current + 1);// 回溯for (int neighbor : neighbors) {graph.adj[current].add(neighbor);graph.adj[neighbor].add(current);}cover.remove(current);return found;
}

九、总结

贪心算法为顶点覆盖问题提供了简单而有效的解决方案,具有明确的近似比保证。通过优先队列优化、并行处理和局部搜索等技术可以显著提高算法性能。虽然存在更复杂的算法可能获得更好的理论保证,但贪心算法在实际应用中因其实现简单、运行高效而广受欢迎。

理解顶点覆盖问题及其贪心解法不仅有助于解决具体的组合优化问题,还能培养对贪心算法设计范式的深刻理解。这种思想可以推广到网络设计、资源分配等多个领域的问题求解中。

更多资源:

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

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


http://www.hkcw.cn/article/thBrrhQwOy.shtml

相关文章

代码随想录算法训练营第十一天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素、栈与队列总结

150. 逆波兰表达式求值--后缀表达式 力扣题目链接(opens new window) 根据 逆波兰表示法&#xff0c;求表达式的值。 有效的运算符包括 , - , * , / 。每个运算对象可以是整数&#xff0c;也可以是另一个逆波兰表达式。 说明&#xff1a; 整数除法只保留整数部分。 给…

女童玩的气球突然爆炸 静电引发惊魂一刻

一位江苏宝妈在六一儿童节前发布了一段视频,提醒家长们不要给孩子买氢气球玩。她描述了自己孩子遇到的一次危险情况:气球突然爆炸,孩子的后脑勺头发被烧焦了一层,手臂上的汗毛也被烧掉了。事发时,这位宝妈正在给孩子喂食鸡腿,突然听到“嘭”的一声,气球在孩子身后爆裂,…

Ubuntu安装CH340驱动教程

Ubuntu22.04安装CH340驱动 3.1 用lsusb查看USB 插上CH340之前 插上CH340之后 输出中包含ID 1a86:7523 QinHeng Electronics CH340 serial converter的信息&#xff0c;这表明CH340设备已经被系统识别。 3.2 查看USB转串口 ls -l /dev/ttyUSB0/dev下没有该设备节点。 用dme…

新人雨中骑“鸡动车”去结婚 创意婚礼引关注

6月1日,在合肥渡仙桥路上,一对新人以独特的方式前往婚礼现场。他们没有选择豪华婚车,甚至没有开车,而是骑着小鸡造型的两轮电动车赶往婚礼现场。这对新人表示,看到这种小鸡造型的电动车觉得很漂亮,便决定用它作为婚车。视频中,这支婚车车队虽然数量不多,但在路上格外显…

上海迪士尼打架事件后续 因拍照引发冲突

5月31日,有网友发布视频称,在上海迪士尼乐园内一对情侣和一家三口发生了冲突。视频中可以看到双方在现场扭打,周围游客纷纷上前劝阻。6月1日,当地相关部门透露,该事件发生在5月31日下午,在迪士尼疯狂动物城的一处拍照打卡点,双方因拍照问题发生争执,随后演变成肢体冲突…

【Python连接数据库基础 02】SQLAlchemy核心实战:SQL表达式构建与执行完全指南

【Python连接数据库基础 02】SQLAlchemy核心实战&#xff1a;SQL表达式构建与执行完全指南 关键词&#xff1a;SQLAlchemy Core、SQL表达式、数据库查询、Python ORM、表达式语言、数据库操作、查询构建、SQLAlchemy教程 摘要&#xff1a;本文深入讲解SQLAlchemy Core的核心功能…

台湾一大学生暗网贩毒被捕 涉案金额超7亿

美国联邦调查局近日破获了暗网毒品交易平台“隐身市场”,该平台的经营者“法老”被发现是24岁的台湾大学资管系学生林睿庠。林睿庠通过贩毒积累了大量财富,三年多时间里非法所得超过1亿美元。林睿庠于2024年5月18日在美国被捕,并面临四项罪名指控,一旦定罪将面临至少终身监…

数据库系统概论(十四)详细讲解SQL中空值的处理

数据库系统概论&#xff08;十四&#xff09;详细讲解SQL中空值的处理 前言一、什么是空值&#xff1f;二、空值是怎么产生的&#xff1f;1. 插入数据时主动留空2. 更新数据时设置为空3. 外连接查询时自然出现 三、如何判断空值&#xff1f;例子&#xff1a;查“漏填数据的学生…

我国代表反驳对华无端指责:无中生有 颠倒黑白 贼喊捉贼

我国代表反驳对华无端指责。5月31日,参加第22届香格里拉对话会的中国代表团团长、中国人民解放军国防大学副校长兼教育长胡钢锋出席《亚太地区海事安全合作》特别论坛,并阐述中方观点。他首先反驳了当天上午大会发言中涉及中方的内容。他表示,我们不接受对中方的无端指责,有…

喊话万科,74岁的王石难有“真还传” 万科面临转型挑战

喊话万科,74岁的王石难有“真还传” 万科面临转型挑战。对于如今的万科来说,他们需要的是“化腐朽为神奇”的钞能力,而不是“剪刀手”。近期地产圈和网络上热议的话题是,如果王石重新回归万科,是否会有奇迹发生。5月27日,万科创始人王石在朋友圈发布了一则长文,表示正在…

国际组织:美债务飙升不仅危及自身更可能引发全球债券市场危机

国际组织:美债务飙升不仅危及自身。5月31日报道,国际金融协会最近的一份报告警告,美国债务飙升的影响不仅限于国内经济,更可能引发全球债券市场危机。报告显示,一些国家的借贷成本往往与美国国债同步变动,这意味着美国国债的波动将对其它债务产生连锁反应。报告写道,“由…

一句古语看懂中方如何应对抹黑!

一句古语看懂中方如何应对抹黑。第22届香格里拉对话会闭幕了这期间,谭主在香会现场看到了美菲防长的无理挑衅甚至连中国记者都变成了菲防长口中的“特工”这说明他们急了,为什么?一句古语看懂中方如何应对抹黑责任编辑:0882

005-C/C++内存管理

C/C内存管理 1. C/C内存分布 栈–存储非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的。内存映射段是高效的I/O映射方式&#xff0c;用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存&#xff0c;做进程间通信&#xff08;这是系统部分的知识…

tex中的表格4:自动表格宽度自动换行tabularx宏包

文章目录 介绍语法规则示例 自定义 X 列的对齐方式多行与多列处理长表格 介绍 在 LaTeX 里&#xff0c;tabularx 是一个很实用的包&#xff0c;它能够创建宽度固定的表格&#xff0c;而且可以自动对列宽进行调整。 语法规则 \usepackage{tabularx} \begin{tabularx}{总宽度}…

数据结构之排序

正值数据结构期末复习之际&#xff0c;遂将排序相关的复习内容记录在此&#xff0c;也算是对知识的一种整理归纳和复习。 常见的排序方法:插入排序、交换排序、选择排序、归并排序、基数排序 其中插入排序又包含直接插入排序、折半插入排序、希尔排序。 交换排序有包括冒泡排…

【Hot 100】118. 杨辉三角

目录 引言杨辉三角我的解题代码优化优化说明 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a5; 标题&#xff1a;【Hot 100】118. 杨辉三角❣️ 寄语&#xff1a;书到用时方恨少&#xff0c;事非经过不知难&#xff01; 引言 …

【Linux网络】传输层TCP协议

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12891150.html 目录 TCP 协议 TCP 协议段格式 确认应答(ACK)机制 超时重传机制 连接管理机制 …

【C语言】C语言经典小游戏:贪吃蛇(上)

文章目录 一、游戏背景及其功能二、Win32 API介绍1、Win32 API2、控制台程序3、定位坐标&#xff08;COORD&#xff09;4、获得句柄&#xff08;GetStdHandle&#xff09;5、获得光标属性&#xff08;GetConsoleCursorInfo&#xff09;1&#xff09;描述光标属性&#xff08;CO…

【Python 算法零基础 4.排序 ⑥ 快速排序】

既有锦绣前程可奔赴&#xff0c;亦有往日岁月可回首 —— 25.5.25 选择排序回顾 ① 遍历数组&#xff1a;从索引 0 到 n-1&#xff08;n 为数组长度&#xff09;。 ② 每轮确定最小值&#xff1a;假设当前索引 i 为最小值索引 min_index。从 i1 到 n-1 遍历&#xff0c;若找到…

Global Securities Markets 第7章知识点总结

一、银行中介的角色定位与核心作用 1. 角色定位&#xff1a;证券流转的核心枢纽 银行作为证券中介&#xff0c;在投资者与证券市场之间扮演三重角色&#xff1a; 资产托管者&#xff1a;负责证券实物或电子形式的安全保管&#xff08;如美国道富银行托管全球ETF资产&#xf…