探索编程世界的宝藏:程序员必掌握的20大算法

2023-10-26

#程序员必须掌握哪些算法?#

文章目录


在这里插入图片描述

1 引言

在当今数字化时代,程序员们仍然需要拥有一把解决问题和优化代码的金钥匙。这些钥匙是算法,它们隐藏在计算机科学的宝藏中,等待着我们去发现和掌握。本篇博文将带你踏上一段引人入胜的探险之旅,揭开程序员必须掌握的20大算法的神秘面纱。从冒泡排序到深度优先搜索,我们将一起探索这些算法的原理、应用场景,为你的学习之旅增添乐趣和激励。

2 冒泡排序算法:编程世界的排序魔法

冒泡排序算法的基本思想是:将待排序的元素按照大小进行比较,较大的元素逐渐“浮”到列表的末尾,而较小的元素逐渐“沉”到列表的开头。通过多次遍历和交换操作,直到整个列表按照升序排列为止。虽然冒泡排序的性能不如一些高级排序算法,但它直观易懂,是学习排序算法的入门必备。

以下是Python代码示例,展示了冒泡排序算法的实现过程:

def bubble_sort(arr):
    n = len(arr)
    
    for i in range(n - 1):
        for j in range(0, n - i - 1):
            # 比较相邻的元素
            if arr[j] > arr[j + 1]:
                # 交换元素位置
                arr[j], arr[j + 1] = arr[j + 1], arr[j]

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print("排序结果:", arr)

通过运行以上代码,你可以看到冒泡排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

冒泡排序算法或许简单,但它的思想对于理解其他高级排序算法以及算法设计的基本原理非常重要。

3 选择排序算法:排序世界的精确挑选器

选择排序算法的思想非常直观:从待排序的序列中选择最小的元素,并将其放置在序列的起始位置。然后,在剩余的未排序部分中继续选择最小的元素,不断将其放置在已排序部分的末尾。经过多次遍历和交换操作,直到整个序列按照升序排列为止。

以下是Python代码示例,展示了选择排序算法的实现过程:

def selection_sort(arr):
    n = len(arr)
    
    for i in range(n - 1):
        min_idx = i
        for j in range(i + 1, n):
            # 找到未排序部分中的最小元素的索引
            if arr[j] < arr[min_idx]:
                min_idx = j
        
        # 将最小元素与当前位置进行交换
        arr[i], arr[min_idx] = arr[min_idx], arr[i]

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
selection_sort(arr)
print("排序结果:", arr)

通过运行以上代码,你可以看到选择排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

选择排序算法不仅简单易懂,而且具有较好的性能。尽管它的时间复杂度为 O(n^2),但在某些情况下,它的性能可能比其他高级排序算法更好。

4 插入排序算法:排序世界的巧妙插珠者

插入排序算法的思想非常巧妙:它将待排序的元素逐个插入到已排序序列的正确位置中。通过不断地比较和交换操作,使得整个序列逐步有序。

以下是Python代码示例,展示了插入排序算法的实现过程:

def insertion_sort(arr):
    n = len(arr)
    
    for i in range(1, n):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            # 将大于key的元素后移
            arr[j + 1] = arr[j]
            j -= 1
        
        # 插入key到正确位置
        arr[j + 1] = key

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
insertion_sort(arr)
print("排序结果:", arr)

通过运行以上代码,你可以看到插入排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

插入排序算法不仅实现简单,而且适用于小型或部分有序的列表。虽然它的平均和最坏情况下的时间复杂度为O(n^2),但在某些情况下,它的性能可能优于其他高级排序算法。

5 快速排序算法:排序世界的分而治之大师

快速排序算法的核心思想是通过选择一个基准元素,将序列分为比基准元素小的一侧和比基准元素大的一侧,然后递归地对两侧的子序列进行排序。

以下是Python代码示例,展示了快速排序算法的实现过程:

def quick_sort(arr, low, high):
    if low < high:
        # 划分序列
        partition_index = partition(arr, low, high)
        
        # 分别对左右子序列进行快速排序
        quick_sort(arr, low, partition_index - 1)
        quick_sort(arr, partition_index + 1, high)
        

def partition(arr, low, high):
    pivot = arr[high]  # 选择最后一个元素作为基准
    i = low - 1  # 指向小于基准的子序列的末尾索引
    
    for j in range(low, high):
        if arr[j] < pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    
    arr[i + 1], arr[high] = arr[high], arr[i + 1]
    return i + 1

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
quick_sort(arr, 0, len(arr) - 1)
print("排序结果:", arr)

通过运行以上代码,你可以看到快速排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

快速排序算法以其高效的平均时间复杂度 O(nlogn) 而被广泛应用。它采用了分治策略,递归地将列表分成更小的子序列,然后通过比较和交换操作将其排序。

6 归并排序算法:排序世界的合而为一大师

归并排序算法的核心思想是将待排序的序列分成两个子序列,不断重复这个过程,直到子序列长度为1。然后,通过合并两个有序的子序列逐步构建有序的结果序列。

以下是Python代码示例,展示了归并排序算法的实现过程:

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        left_half = arr[:mid]
        right_half = arr[mid:]
        
        merge_sort(left_half)
        merge_sort(right_half)
        
        merge(arr, left_half, right_half)

def merge(arr, left_half, right_half):
    i = j = k = 0
    
    while i < len(left_half) and j < len(right_half):
        if left_half[i] < right_half[j]:
            arr[k] = left_half[i]
            i += 1
        else:
            arr[k] = right_half[j]
            j += 1
        k += 1
    
    while i < len(left_half):
        arr[k] = left_half[i]
        i += 1
        k += 1
    
    while j < len(right_half):
        arr[k] = right_half[j]
        j += 1
        k += 1

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
merge_sort(arr)
print("排序结果:", arr)

通过运行以上代码,你可以看到归并排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

归并排序算法以其稳定的时间复杂度 O(nlogn) 和可靠的性能而受到广泛应用。它通过将序列递归地分成两个子序列,然后将这些子序列合并为一个有序的结果序列。

7 堆排序算法:排序世界的二叉堆巨匠

堆排序算法的核心思想是通过构建一个最大堆或最小堆来实现排序。最大堆是一种二叉树结构,每个父节点的值都大于或等于其子节点的值;最小堆则相反,每个父节点的值都小于或等于其子节点的值。通过不断交换根节点和最后一个节点,并对剩余节点进行堆化操作,堆排序算法可以得到一个有序的结果序列。

以下是Python代码示例,展示了堆排序算法的实现过程:

def heap_sort(arr):
    n = len(arr)
    
    # 构建最大堆
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)
    
    # 依次提取根节点(最大值)并进行堆化操作
    for i in range(n - 1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        heapify(arr, i, 0)

def heapify(arr, n, i):
    largest = i
    left = 2 * i + 1
    right = 2 * i + 2
    
    if left < n and arr[left] > arr[largest]:
        largest = left
    
    if right < n and arr[right] > arr[largest]:
        largest = right
    
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
heap_sort(arr)
print("排序结果:", arr)

通过运行以上代码,你可以看到堆排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

堆排序算法以其稳定的平均时间复杂度 O(nlogn) 而被广泛应用。它利用二叉堆的特性,不断交换根节点和最后一个节点,对剩余节点进行堆化操作,从而实现排序。

8 计数排序算法:排序世界的数字统计大师

计数排序算法的核心思想是通过先统计序列中每个元素出现的次数,然后根据这些统计信息将元素按照顺序重新排列。它适用于非负整数的排序,且时间复杂度为O(n+k),其中n是序列的长度,k是序列中出现的最大值。

以下是Python代码示例,展示了计数排序算法的实现过程:

def counting_sort(arr):
    max_value = max(arr)
    count = [0] * (max_value + 1)
    result = [0] * len(arr)
    
    # 统计每个元素出现的次数
    for num in arr:
        count[num] += 1
    
    # 计算每个元素在排序后的序列中的位置
    for i in range(1, max_value + 1):
        count[i] += count[i - 1]
    
    # 构建排序后的序列
    for num in arr:
        result[count[num] - 1] = num
        count[num] -= 1
    
    return result

# 测试
arr = [64, 34, 25, 12, 22, 11, 90]
sorted_arr = counting_sort(arr)
print("排序结果:", sorted_arr)

通过运行以上代码,你可以看到计数排序算法将列表 [64, 34, 25, 12, 22, 11, 90] 按照升序排列后的结果。

计数排序算法以其线性时间复杂度和稳定性而受到广泛应用。它通过统计序列中每个元素的出现次数,并利用这些统计信息构建有序结果序列。

9 基数排序算法:排序世界的位数魔法师

基数排序算法的核心思想是从低位到高位对待排序的元素进行排序。它利用了数字的位数特性,通过多次分配和收集的过程,最终可以得到一个有序的结果。基数排序算法适用于元素为非负整数的排序,且时间复杂度为O(d * (n + k)),其中d是数字的位数,n是序列的长度,k是每个位的取值范围。
以下是Python代码示例,展示了基数排序算法的实现过程:

def counting_sort(arr, exp):
    n = len(arr)
    count = [0] * 10
    result = [0] * n
    
    # 统计每个位上的出现次数
    for i in range(n):
        index = arr[i] // exp
        count[index % 10] += 1
    
    # 计算每个位上元素的位置
    for i in range(1, 10):
        count[i] += count[i - 1]
    
    # 构建排序后的序列
    for i in range(n - 1, -1, -1):
        index = arr[i] // exp
        result[count[index % 10] - 1] = arr[i]
        count[index % 10] -= 1
    
    # 更新原序列
    for i in range(n):
        arr[i] = result[i]

def radix_sort(arr):
    max_value = max(arr)
    exp = 1
    
    # 从低位到高位依次进行排序
    while max_value // exp > 0:
        counting_sort(arr, exp)
        exp *= 10

# 测试
arr = [170, 45, 75, 90, 802, 24, 2, 66]
radix_sort(arr)
print("排序结果:", arr)

通过运行以上代码,你可以看到基数排序算法将列表 [170, 45, 75, 90, 802, 24, 2, 66] 按照升序排列后的结果。

基数排序算法以其高效的时间复杂度和稳定性而受到广泛应用。它利用数字的位数特性,通过多次分配和收集的过程实现排序。

10 深度优先搜索算法:探索图的迷宫穿越之旅

深度优先搜索算法的核心思想是通过递归地探索图的所有可能路径,直到找到目标节点或无法继续前进为止。它通过深入搜索图的每个分支,直到无法再继续为止,然后回溯到上一个节点,继续搜索其他未探索的分支。深度优先搜索常用于解决迷宫问题、图遍历和连通性问题等。

以下是Python代码示例,展示了深度优先搜索算法的实现过程:

def dfs(graph, start, visited):
    # 标记当前节点为已访问
    visited.add(start)
    print(start, end=" ")
    
    # 递归地遍历当前节点的邻接节点
    for neighbor in graph[start]:
        if neighbor not in visited:
            dfs(graph, neighbor, visited)

# 创建图的邻接列表表示
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}
visited = set()

# 从节点'A'开始进行深度优先搜索
dfs(graph, 'A', visited)

通过运行以上代码,你可以看到从节点’A’出发进行深度优先搜索的结果。

深度优先搜索算法以其简单、灵活和可变化的特性而受到广泛应用。它通过递归地探索图的所有可能路径,可以解决许多与图相关的问题。

11 广度优先搜索算法:一步一步扩展探索之旅

广度优先搜索算法的核心思想是利用队列数据结构,逐层扩展搜索目标节点周围的节点。它从起始节点开始,按照距离起始节点的层级顺序逐层探索,并在每一层按照从左到右的顺序对节点进行访问。广度优先搜索常用于解决最短路径问题、连通性问题和寻找图中特定节点等。

以下是Python代码示例,展示了广度优先搜索算法的实现过程:

from collections import deque

def bfs(graph, start):
    visited = set()
    queue = deque([start])
    
    while queue:
        node = queue.popleft()
        if node not in visited:
            print(node, end=" ")
            visited.add(node)
            queue.extend(graph[node])

# 创建图的邻接列表表示
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 从节点'A'开始进行广度优先搜索
bfs(graph, 'A')

通过运行以上代码,你可以看到从节点’A’出发进行广度优先搜索的结果。

广度优先搜索算法以其逐层扩展和广泛探索的特性而受到广泛应用。它利用队列数据结构,逐层扩展搜索目标节点周围的节点,可以解决许多与图相关的问题。

12 迪杰斯特拉算法:寻找最短路径的探索之旅

迪杰斯特拉算法(Dijkstra’s Algorithm)是一种常用且高效的图算法,用于在带权重的图中寻找从起始节点到目标节点的最短路径。本篇博文将详细介绍迪杰斯特拉算法的原理和实现方法,并提供Python代码,带你一起踏上最短路径的探索之旅。

迪杰斯特拉算法的核心思想是通过启发式的贪心策略,逐步更新起始节点到其他节点的最短距离,并逐步确定最短路径。它维护一个距离表,记录每个节点到起始节点的当前最短距离,并使用优先级队列来选择下一个要扩展的节点。迪杰斯特拉算法常用于路由选择、网络优化和资源分配等问题。

以下是Python代码示例,展示了迪杰斯特拉算法的实现过程:

import heapq

def dijkstra(graph, start):
    distances = {node: float('inf') for node in graph}
    distances[start] = 0
    queue = [(0, start)]
    
    while queue:
        current_distance, current_node = heapq.heappop(queue)
        
        if current_distance > distances[current_node]:
            continue
        
        for neighbor, weight in graph[current_node].items():
            distance = current_distance + weight
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(queue, (distance, neighbor))
    
    return distances

# 创建图的邻接字典表示(使用邻接矩阵也可)
graph = {
    'A': {'B': 5, 'C': 2},
    'B': {'A': 5, 'D': 1, 'E': 6},
    'C': {'A': 2, 'F': 8},
    'D': {'B': 1},
    'E': {'B': 6, 'F': 3},
    'F': {'C': 8, 'E': 3}
}

# 从节点'A'开始使用迪杰斯特拉算法寻找最短路径
start_node = 'A'
shortest_distances = dijkstra(graph, start_node)

# 输出最短路径结果
for node, distance in shortest_distances.items():
    print(f"The shortest distance from {start_node} to {node} is {distance}")

通过运行以上代码,你可以得到从起始节点’A’到其他节点的最短距离结果。

迪杰斯特拉算法以其高效且准确的特性而受到广泛应用。它利用启发式的贪心策略逐步更新最短距离,并逐步确定最短路径。

13 动态规划算法:优化子问题,实现最优解之旅

动态规划(Dynamic Programming)算法是一种常用且强大的算法技术,用于解决具有重叠子问题性质的优化问题。动态规划的关键思想是将一个大问题分解为多个重叠子问题,并保存子问题的解,以避免重复计算。通过自底向上或自顶向下的方式,动态规划算法逐步求解子问题,最终得到问题的最优解。动态规划广泛应用于求解背包问题、路径计数问题、最长公共子序列问题以及其他许多复杂的优化问题。

以下是Python代码示例,展示了动态规划算法的实现过程:

def fibonacci(n):
    fib = [0, 1]
    
    for i in range(2, n+1):
        fib.append(fib[i-1] + fib[i-2])
    
    return fib[n]

# 计算斐波那契数列的第10个数
n = 10
result = fibonacci(n)

print(f"The Fibonacci number at index {n} is {result}")

通过运行以上代码,你可以得到斐波那契数列中第10个数的结果。

动态规划算法通过优化子问题的求解,实现了高效的最优解求解过程。它将一个大问题分解为多个重叠子问题,并使用存储技术避免重复计算,从而提高算法的效率。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

探索编程世界的宝藏:程序员必掌握的20大算法 的相关文章

随机推荐

  • 【C语言】螺旋数组

    螺旋数组的打印 程序C语言代码 更改宏定义的数值即可实现螺旋数组行列的变化 include stdio h define ROW 5 宏定义行 define COL 5 宏定义列 void main int arr ROW COL 0 in
  • Python Decorators(二):Decorator参数

    Python Decorators II Decorator Arguments October 19 2008 本文是Python 3 Patterns Idioms Python3之模式和用法 一书的章节节选第二部分 点击这里阅读第一部
  • Kotlin数据类型(一:数据类型)

    一 Boolean Boolean类型有两种类型的 true flase val a Boolean true val b Boolean false 二 Number数据类型 package net println kotlin auth
  • 强化学习 DQN 速成

    强化学习 DQN 速成 这是对 深度强化学习 王树森 张志华 中 DQN 部分的缩写以及部分内容的个人解读 书中的 DQN 是一个相对终极版本的存在 相信体量会比网络上其他资料要大很多 基本概念 我们通过贪吃蛇来引入几个基本概念 符号 中文
  • Flink Windows(窗口)详解

    Windows 窗口 Windows是流计算的核心 Windows将流分成有限大小的 buckets 我们可以在其上应用聚合计算 ProcessWindowFunction ReduceFunction AggregateFunction或
  • MySQL redo log和undo log

    Redo Log REDO LOG称为重做日志 当MySQL服务器意外崩溃或者宕机后 保证已经提交的事务持久化到磁盘中 持久性 InnoDB是以页为单位去操作记录的 增删改查都会加载整个页到buffer pool中 磁盘 gt 内存 事务中
  • Matlab矩阵处理

    一 通用的特殊矩阵 zero m zeros m n zero size A 产生全为零的矩阵 格式下同 ones 产生全为一的矩度阵 eye 产生单位矩阵 rand 产生在 0 1 区间均匀分布的矩阵 randn 产生均值为0 方差为1的
  • C计数问题---2023河南萌新联赛第(三)场:郑州大学

    解析 n 可以分成两个数 记录每个数的因子对数 乘起来即可 注意当因子相同时 只 1 include
  • Java文件类型校验之Apache Tika

    一 背景 判断文件类型一般可采用两种方式 1 后缀名判断 简单易操作 但无法准确判断类型 2 文件头信息判断 通常可以判断文件类型 但有些文件类型无法判断 如word和excel头信息的前几个字节是一样的 无法判断 使用apache tik
  • flink watermark 生成机制与总结

    flink watermark 生成机制与总结 watermark 介绍 watermark生成方式 watermark 的生成值算法策略 watermark策略设置代码 watermark源码分析 watermark源码调用流程debug
  • 你知道几种延迟队列的实现方案?

    在开发中 往往会遇到一些关于延时任务的需求 例如 生成订单30分钟未支付 则自动取消 生成订单60秒后 给用户发短信 对上述的任务 我们给一个专业的名字来形容 那就是延时任务 那么这里就会产生一个问题 这个延时任务和定时任务的区别究竟在哪里
  • Reid训练代码之数据集处理

    本篇文章是对yolov5 reid这篇文章训练部分的详解 该项目目录为 config reid输入大小 数据集名称 损失函数等配置 configs 训练时期超参数定义 data 存储数据集和数据处理等代码 以及yolov5类别名称等 eng
  • 怎样更改itunes备份位置_什么是iTunes备份文件?

    由于它是由Apple创建的 因此iTunes改变了用户组织和播放音乐和视频的方式 iTunes已经允许数百万用户通过iTunes Store下载他们喜爱的曲目 歌曲和视频 值得庆幸的是 iTunes拥有一个先进的备份系统 能够备份和恢复Ip
  • Android libdvm.so 与 libart.so

    Android libdvm so 与 libart so 系统升级到5 1之后 发现system lib 下面没有libdvm so了 只剩下了libart so 对于libart模式 从4 4就在Developer optins里面就可
  • FsonFormat Eclipse Plugin 一键解决复杂JSON ,快速实现JavaBean

    简介 当开发人员或者测试人员在开发或者测试接口中 去获取到接口返回的结果值时 都要通过JSONObject和JSONArray解析json结构 然后再通过For循环遍历相应的Key 最后把value值进行App展示或者校验是否预期结果 编写
  • 有关树莓派+arduino构建小车

    这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题 有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一个表格 设定内容居中 居左 居右 Sma
  • eclipse中没有runtime environments_Go语言中的panic和recover

    初识别panic和recover 本节将分析两个经常成对出现的关键字 panic 和 recover 这两个关键字都与 defer 有千丝万缕的联系 也都是 Go 语言中的内置函数 但是提供的功能却是互补的 panic 能够改变程序的控制流
  • opencv 图像雾检测_雾的检测算法

    雾的检测算法相对来说文献不是很多 这次和大家介绍两篇相对来说比较容易实现的两篇文章 其中一篇是基于灰度直方图的方式进行分析检测 另一篇是将rgb图像空间转化为hsv空间进行分析检测 1 灰度图检测 首先来说第一片 Fog Detection
  • 如何用ai写文章?这三个软件可以自动生成文章

    随着人工智能技术的不断发展 ai写作已经成为了当今的热门话题 它是指利用机器学习 自然语言处理等技术 让机器能够像人类一样写作 相较于传统写作方式 ai写作大大提高了写作的效率和质量 可以让我们的创意和技术相融合 其应用范围也非常广泛 无论
  • 探索编程世界的宝藏:程序员必掌握的20大算法

    程序员必须掌握哪些算法 文章目录 1 引言 2 冒泡排序算法 编程世界的排序魔法 3 选择排序算法 排序世界的精确挑选器 4 插入排序算法 排序世界的巧妙插珠者 5 快速排序算法 排序世界的分而治之大师 6 归并排序算法 排序世界的合而为一