经验分享|作为程序员之后了解到的算法知识

欢迎关注博主 六月暴雪飞梨花 或加入【六月暴雪飞梨花】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。
在这里插入图片描述

一个程序员一生中可能会邂逅各种各样的算法,但总有那么几种,是作为一个程序员一定会遇见且大概率需要掌握的算法。今天就来聊聊这些十分重要的“必抓!”算法吧~

一 引言

1.1 算法的定义

算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令。它代表着用系统的方法描述解决问题的策略机制。算法能够处理一定规范的输入,在有限时间内获得所要求的输出。

1.2 算法的特征

一个算法具有以下四个重要的特征:有穷性(Finiteness)、确切性(Definiteness)、输入和输出项 (Input/Ouput)、可行性(Effectiveness)。

1.3 算法的分类

算法可以根据不同的标准进行分类。

  • 算法宏观泛义分类:有限确定性算法、有限不定性算法和无限算法。
  • 算法设计原理分类:搜索算法、排序算法、图算法、动态规划算法、回溯算法。
  • 算法的使用用途分类:数值算法、字符串算法、图像处理算法、机器学习算法、并行计算算法。

1.4 算法的描述

在计算机中,如何描述算法,主要有自然语言,流程图,代码等。

在流程图中,描述算法可使用如下的标识符号。
在这里插入图片描述

在代码中的算法可以描述为如下

public class RecursionExample {  public static void main(String[] args) {  int n = 5;  int result = factorial(n);  System.out.println("Factorial of " + n + " is " + result);  }  public static int factorial(int n) {  if (n == 0) {  return 1;  } else {  return n * factorial(n - 1);  }  }  
}

使用动态图演示如下:
在这里插入图片描述

二 常见算法介绍

提示:介绍常见的排序算法,查找算法、图论算法和字符串算法等等

2.1 分治法

【基本思想】
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。

【解题思路】
分解->求解->合并

【实例解析】
快速排序(Quick Sort):选取基准数(比如第一个),比我小的往前排,比我大的往后排。

public class QuickSort {  public static void quickSort(int[] arr, int low, int high) {  if (low < high) {  // pi 是分区索引,arr[pi] 的位置已经确定了  int pi = partition(arr, low, high);  // 通过递归调用,分别对pi的左右两部分进行排序  quickSort(arr, low, pi - 1);  quickSort(arr, pi + 1, high);  }  }  // 这个函数用来找出数组中最大元素的位置,并返回该位置  public static int partition(int[] arr, int low, int high) {  // 选择最右边的元素作为基准  int pivot = arr[high];   int i = (low - 1); // 指向最小元素的指针  for (int j = low; j < high; j++) {  // 如果当前元素小于或等于 pivot  if (arr[j] <= pivot) {  i++;  // 交换 arr[i] 和 arr[j]  int temp = arr[i];  arr[i] = arr[j];  arr[j] = temp;  }  }  // 交换 arr[i+1] 和 arr[high] (或者基准)  int temp = arr[i + 1];  arr[i + 1] = arr[high];  arr[high] = temp;  return i + 1;  }  public static void main(String args[]) {  int arr[] = {10, 7, 8, 9, 1, 5};  int n = arr.length;  quickSort(arr, 0, n - 1);  System.out.println("排序后的数组:");  for (int i = 0; i < n; ++i) {  System.out.print(arr[i] + " ");  }  System.out.println();  }  
}

2.2 贪心法

【基本思想】
局部最优解,可能得到整体最优解或是最优解的近似解。

【解题思路】
在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

【实例解析】
Prim算法(最小生成树算法之一,还有一个为Kruskal算法)。

import java.util.Arrays;  class Graph {  private static final int INF = Integer.MAX_VALUE;  private int numVertices;  private int[][] adjacencyMatrix;  public Graph(int numVertices) {  this.numVertices = numVertices;  adjacencyMatrix = new int[numVertices][numVertices];  for (int[] row : adjacencyMatrix)  Arrays.fill(row, INF);  }  public void addEdge(int src, int dest, int weight) {  adjacencyMatrix[src][dest] = weight;  adjacencyMatrix[dest][src] = weight;  }  private int getMinVertex(boolean[] mstSet, int[] key) {  int minKey = INF;  int vertex = -1;  for (int i = 0; i < numVertices; i++) {  if (!mstSet[i] && key[i] < minKey) {  minKey = key[i];  vertex = i;  }  }  return vertex;  }  public void primMST() {  boolean[] mstSet = new boolean[numVertices];  int[] key = new int[numVertices];  int[] parent = new int[numVertices];  Arrays.fill(key, INF);  Arrays.fill(parent, -1);  key[0] = 0;   for (int i = 0; i < numVertices - 1; i++) {  int minVertex = getMinVertex(mstSet, key);  mstSet[minVertex] = true;  for (int j = 0; j < numVertices; j++) {  int edgeWeight = adjacencyMatrix[minVertex][j];  if (edgeWeight != INF && !mstSet[j] && edgeWeight < key[j]) {  parent[j] = minVertex;  key[j] = edgeWeight;  }  }  }  printMST(parent, key);  }  private void printMST(int[] parent, int[] key) {  System.out.println("Edge \tWeight");  for (int i = 1; i < numVertices; i++)  System.out.println(parent[i] + " - " + i + "\t" + key[i]);  }  
}public static void main(String[] args) {  Graph graph = new Graph(5);  graph.addEdge(0, 1, 2);  graph.addEdge(0, 3, 6);  graph.addEdge(1, 2, 3);  graph.addEdge(1, 3, 8);  graph.addEdge(1, 4, 5);  graph.addEdge(2, 4, 7);  graph.addEdge(3, 4, 9);  graph.primMST();  
}

1.3 分支限界法

【基本思想】
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

【解题思路】
找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解.

【实例解析】
优先队列式分支限界法。

import java.util.PriorityQueue;  public class BranchAndBound {  // 定义节点类  static class Node implements Comparable<Node> {  int level; // 节点层数  int cost; // 节点代价  boolean isLeaf; // 是否为叶子节点  Node(int level, int cost, boolean isLeaf) {  this.level = level;  this.cost = cost;  this.isLeaf = isLeaf;  }  // 根据节点优先级进行比较  public int compareTo(Node other) {  return Integer.compare(cost, other.cost);  }  }  // 优先队列式分支限界法  public static void branchAndBound(Node root) {  PriorityQueue<Node> queue = new PriorityQueue<>(); // 创建优先队列  queue.offer(root); // 将根节点加入队列中  while (!queue.isEmpty()) {  Node node = queue.poll(); // 选择优先级最高的节点作为当前扩展节点  if (node.isLeaf) {  // 如果当前扩展节点是目标节点,则算法结束  System.out.println("目标节点找到!");  break;  } else {  // 对当前扩展节点进行扩展,生成所有子节点,并将它们加入优先队列中  for (int i = 0; i < 2; i++) {  int level = node.level + 1;  int cost = node.cost + i;  boolean isLeaf = (i == 1); // 假设只有一个叶子节点  Node child = new Node(level, cost, isLeaf);  queue.offer(child); // 将子节点加入队列中  }  }  }  }  public static void main(String[] args) {  int level = 0; // 根节点层数为0  int cost = 0; // 根节点代价为0  boolean isLeaf = false; // 根节点不是叶子节点  Node root = new Node(level, cost, isLeaf); // 创建根节点  branchAndBound(root); // 运行分支限界法算法  }  
}

三 重点算法总结

3.1 算法的应用场景

算法是解决特定问题或执行特定任务的一组明确的步骤。

  • 排序算法:主要应用在计算机科学中,排序算法用于将一组数据按照特定的顺序(例如升序或降序)排列。
  • 搜索算法:搜索算法用于在数据结构(如数组,链表,树等)中查找特定的元素。这些算法在互联网搜索引擎,数据库系统,文件管理系统等场景中有着广泛的应用。
  • 机器学习算法:从大量数据中提取有用的模式,并做出预测或决策。它们广泛应用于图像和语音识别,推荐系统,预测分析,自动驾驶等领域。
  • 加密算法:在网络安全领域,加密算法用于保护数据的机密性和完整性。这些算法广泛用于电子商务,电子银行,远程办公等场景。
  • 图算法:图算法用于处理图形结构数据,如社交网络、互联网路由、交通网络等。它们在这些复杂网络中寻找路径、检测环路、计算距离等问题。

3.2 如何学习和掌握算法

算法是计算机科学的基础,它们对于解决复杂问题,优化解决方案以及提高程序性能至关重要。

学习算法是一个循序渐进的过程。

  1. 个人可以定期进行算法培训、参加算法挑战项目(在参战过程中获取奖励和认可)。
  2. 机构和企业鼓励员工参加算法竞赛、建立算法基金支持,为那些对算法有深入研究愿望的程序员提供一定的资金支持,这样可以鼓励他们深入研究,发表高质量的研究成果。
  3. 最后,共同推广常用算法以及应用。

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

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

相关文章

LabVIEW开发航天器模拟器的姿态控制和反作用轮动量管理

LabVIEW开发航天器模拟器的姿态控制和反作用轮动量管理 在过去十年中&#xff0c;航天器一直是现代技术进步的先决条件。迄今为止&#xff0c;为了更好地完成各种实际任务&#xff0c;已经在航天器姿态控制领域进行了大量研究。航天器一旦进入太空&#xff0c;就容易出现不确定…

【深度学习实验】前馈神经网络(一):使用PyTorch构建神经网络的基本步骤

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入库 1. 定义x,w,b 2. 计算净活性值z 3. 实例化线性层并进行前向传播 4. 打印结果 5. 代码整合 一、实验介绍 本实验使用了PyTorch库来构建和操作神经网络模型&#xff0c;主要是关…

算法训练 第三周

二、环形链表 本题给了我们一个链表的头节点&#xff0c;需要我们判断这个链表之中是否存在环状结构&#xff0c;如果存在返回true&#xff0c;如果不存在则返回false。 1.hash表 我们可以从头遍历整个链表&#xff0c;并将遍历到的节点放入一个hashset中&#xff0c;当我们遍…

北邮22级信通院数电:Verilog-FPGA(2)modelsim北邮信通专属下载、破解教程

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 1.下载 2.解压打开 3.modelsim初安装 4.…

深度剖析Linux信号机制

文章目录 信号的概念信号的分类信号的产生方式从键盘获取通过系统调用硬件异常软件条件 如何处理信号的到来信号的更深入剖析信号的处理动作是何时进行的&#xff1f;当有一大批同种信号到来时会怎样&#xff1f;Linux也提供了一批信号相关的系统调用 信号的概念 Linux中的信号…

C语言——通讯录管理系统

通讯录管理系统项目简介 功能说明 控制台黑窗口实现程序需要满足以下几个功能 程序开始运行时首先显示选择菜单界面&#xff0c;根据用户输入确定实现何种功能 程序界面 代码实现 多文件实现 和之前写的实战项目类似&#xff0c;这里同样采用多文件实现的方式 多文件写代码…

day3_QT

day3_QT 1、文件保存2、始终事件 -闹钟 1、文件保存 2、始终事件 -闹钟 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> #include <QTime> #include <QTextToSpeech>QT_BEGIN_NAMESPACE namespace Ui { clas…

Qt --- Day03

<?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Widget</class><widget class"QWidget" name"Widget"><property name"geometry"><rect><x>0…

fatal error: linux/compiler-gcc9.h: No such file or directory

linux 找到README文件 cd /mnt/e/CLionProjects/linux-3.10.99 sudo useradd linux3x sudo passwd linux3x sudo mkdir /home/linux3x sudo chown linux3x:linu3x /home/linux3x sudo chmod 755 /home/linux3x su - linux3x mkdir ~/build mkdir ~/build/kernel exit make O/…

目标检测Neck:FPN(Feature Pyramid Network)与PAN(附torch代码)

文章目录 0. 前言1. FPN1.1 FPN核心思想与步骤1.2 FPN的融合过程2. PAN2.1 PANet2.2 原版2.3 mmdetection中yolo_neck版本2.4 nanodet版本ReferenceFPN和PAN都是用于解决在目标检测中特征金字塔网络(FPN)在多尺度检测任务上的不足的方法。下面分别详细介绍一下它们的原理和区别…

Docker 容器设置为自动重启

Docker自动重启原因 Docker自动重启通常是由以下几个原因导致的&#xff1a; 程序崩溃系统内存不足系统进程使用过多CPU和RAM导致的阻塞docker容器被杀死或重新启动&#xff0c;导致应用程序中断网络中断 当这些问题出现时&#xff0c;Docker会自动重启运行中的服务来尝试解…

malloc与free

目录 前提须知&#xff1a; malloc&#xff1a; 大意&#xff1a; 头文件&#xff1a; 申请空间&#xff1a; 判断是否申请成功&#xff1a; 使用空间&#xff1a; 结果&#xff1a; 整体代码&#xff1a; malloc申请的空间怎么回收呢? 注意事项&#xff1a; free:…

【入门篇】ClickHouse最优秀的开源列式存储数据库

文章目录 一、什么是ClickHouse&#xff1f;OLAP场景的关键特征列式数据库更适合OLAP场景的原因输入/输出CPU 1.1 ClickHouse的定义与发展历程1.2 ClickHouse的版本介绍 二、ClickHouse的主要特性2.1 高性能的列式存储2.2 实时的分析查询2.3 高度可扩展性2.4 数据压缩2.5 SQL支…

PHP自己的框架2.0结合容器技术(重构篇二)

目录 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 3、框架使用容器类来执行public/index.php 4、运行效果还是一样 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 什么是容器&#xff1f;容器就相当于盒子&#xff0c;把很多类放里…

Postman应用——控制台调试

当你在测试脚本中遇到错误或意外行为时&#xff0c;Postman控制台可以帮助你识别&#xff0c;通过将console.log调试语句与你的测试断言相结合&#xff0c;你可以检查http请求和响应的内容&#xff0c;以及变量之类的。 通常可以使用控制台日志来标记代码执行&#xff0c;有时…

【分布式】分布式ID

目录 前言一、雪花算法snowflake1. 组成2. 优缺点3. 时钟回拨怎么解决a. 时钟回拨b. 解决方案 4. 项目中如何使用 二、基于Redis三、基于Zookeeper四、号段模式五、指定步长的自增ID六、UUID参考 六、扩展总结 前言 分布式场景下&#xff0c;一张表可能分散到多个数据结点上。因…

【JavaEE】多线程案例-单例模式

文章目录 1. 前言2. 什么是单例模式3. 如何实现单例模式3.1 饿汉模式3.2 懒汉模式4. 解决单例模式中遇到的线程安全问题4.1 加锁4.2 加上一个判断解决频繁加锁问题4.2 解决因指令重排序造成的线程不安全问题 1. 前言 单例模式是我们面试中最常考到的设计模式。什么是设计模式呢…

【Redis】深入探索 Redis 主从结构的创建、配置及其底层原理

文章目录 前言一、对 Redis 主从结构的认识1.1 什么是主从结构1.2 主从结构解决的问题 二、主从结构创建2.1 配置并建立从节点2.2.1 从节点配置文件2.2.2 启动并连接 Redis 主从节点2.2.3 SLAVEOF 命令2.2.4 断开主从关系 2.2 查看主从节点的信息2.2.1 INFO REPLICATION 命令2.…

《DevOps实践指南》- 读书笔记(六)

DevOps实践指南 Part 4 第二步 &#xff1a;反馈的技术实践17. 将假设驱动的开发和A/B测试融入日常工作17.1 A/B 测试简史17.2 在功能测试中集成 A/B 测试17.3 在发布中集成 A/B 测试17.4 在功能规划中集成 A/B 测试17.5 小结 18. 建立评审和协作流程以提升当前工作的质量18.1 …

04条件构造器和常用接口

条件构造器和常用接口 wapper介绍 条件构造器的两个条件之间默认就是AND并列关系,如果需要或者的关系则需要调用构造器的or()方法 条件构造器类型作用Wrapper条件构造抽象类,最顶端父类AbstractWrapper生成SQL的where条件QueryWrapper封装查询或删除的条件UpdateWrapper封装修…