常见排序及查找算法

news2024/11/15 15:36:10

内容引用自:
【数据结构和算法】十大经典排序算法(动图演示)

算法复杂度

在这里插入图片描述

1、冒泡排序

1.1、动图演示

  • 遍历列表数据,共遍历length(列表)次,每一次的遍历都要从左到右进行两两比对,左边比右边小,那么值就调换,否则进行往后两位的比对值;
  • 每遍历一次,可以得到一个最大值(第一次遍历时最大值,后面遍历得到的应该叫次最大值)

在这里插入图片描述

1.2、代码

def bubble_sort(arr):
    for i in range(len(arr)):
        for j in range(len(arr) - 1 - i):
            if arr[j] > arr[j+1]:
                tmp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = tmp
            # # print(arr)
            print(arr)

    return arr


if __name__ == '__main__':
    bubble_sort([9, 8, 7, 6, 5, 4, 3, 2, 1])

2、快速排序

2.1 、核心思想:

  1. 在待排序的元素任取一个元素作为基准(通常选第一个元素(arr[left]),称为基准元素(pivot),)
  2. 将待排序的元素进行分块,比基准元素大的元素移动到基准元素的右侧,比基准元素小的移动到作左侧,从而一趟排序过程,就可以锁定基准元素的最终位置
  3. 对左右两个分块重复以上步骤直到所有元素都是有序的(递归过程)

2.2、静态图(来源:图解快速排序),动图不那么好理解:

在这里插入图片描述

2.3、代码:

def quick_sort(arr, left, right):
    print("原始数据:\n" + str(arr))

    if left >= right:
        return

    i = left
    j = right
    pivot = arr[left]

    while i != j:
        while (i < j) and arr[j] > pivot:  # 这里不可以等于,等于会导致1,2,1的情况,无法实现排序
            j -= 1
            
        # 比pivot小, 就将小的值替换到pivot前面去,交换值
        p = arr[i]
        arr[i] = arr[j]
        arr[j] = p

        print(arr)

        # 因为上一步arr[j]与arr[i]值调换以后,arr[i]一定是比小的,所以不用提前 i += 1,下方的while会自动给执行一次i += 1
        while (i < j) and arr[i] <= pivot:
            i += 1
		
		# 比pivot大, 就将大的值替换到pivot后面去,交换值
        p = arr[i]
        arr[i] = arr[j]
        arr[j] = p

        print(arr)

    quick_sort(arr, left, i - 1)
    quick_sort(arr, i+1, right)

    return


print(quick_sort([3, 6, 8, 10, 1, 2, 1], 0, 6))
# print(quick_sort([6, 6, 8, 10, 1, 2, 1], 0, 6))
# print(quick_sort([6, 6, 6, 10, 1, 2, 1], 0, 6))
# print(quick_sort([9, 8, 7, 6, 5, 4, 3], 0, 6))

2.4、结果:

原始数据:
[3, 6, 8, 10, 1, 2, 1]
[1, 6, 8, 10, 1, 2, 3]
[1, 3, 8, 10, 1, 2, 6]
[1, 2, 8, 10, 1, 3, 6]
[1, 2, 3, 10, 1, 8, 6]
[1, 2, 1, 10, 3, 8, 6]
[1, 2, 1, 3, 10, 8, 6]
[1, 2, 1, 3, 10, 8, 6]
[1, 2, 1, 3, 10, 8, 6]
原始数据:
[1, 2, 1, 3, 10, 8, 6]
[1, 2, 1, 3, 10, 8, 6]
[1, 1, 2, 3, 10, 8, 6]
[1, 1, 2, 3, 10, 8, 6]
[1, 1, 2, 3, 10, 8, 6]
原始数据:
[1, 1, 2, 3, 10, 8, 6]
原始数据:
[1, 1, 2, 3, 10, 8, 6]
原始数据:
[1, 1, 2, 3, 10, 8, 6]
[1, 1, 2, 3, 6, 8, 10]

3、选择排序(Selection Sort)

3.1、核心思想

选择排序(Selection-sort)是一种简单直观的排序算法。
它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

3.2、动图演示

在这里插入图片描述

3.3、代码

def selection_sort(arr):

    for i in range(len(arr)):
        print(arr)
        for j in range(i + 1, len(arr)):
            min_num = arr[i]
            if min_num > arr[j]:
                p = arr[j]
                arr[j] = arr[i]
                arr[i] = p
    # print(arr)


selection_sort([3, 2, 10, 2, 9, 6, 2])

[3, 2, 10, 2, 9, 6, 2]
[2, 3, 10, 2, 9, 6, 2]
[2, 2, 10, 3, 9, 6, 2]
[2, 2, 2, 10, 9, 6, 3]
[2, 2, 2, 3, 10, 9, 6]
[2, 2, 2, 3, 6, 10, 9]
[2, 2, 2, 3, 6, 9, 10]

4、插入排序(Insertion Sort)

4.1、核心思想

插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

4.2、动图演示

在这里插入图片描述

4.3、代码

def insertion_sort(arr):

    for i in range(1, len(arr)):
        preIdx = i - 1
        current = arr[i]

        print("第" + str(i) + "次循环输入数据:\n" + str(arr))

        # 下方这个跳出循环的部分比较巧妙,两个条件,缺一不可
        while preIdx >= 0 and arr[preIdx] > current:
            arr[preIdx + 1] = arr[preIdx]
            preIdx -= 1

            print("中间过程========" + str(arr))
        arr[preIdx + 1] = current
        print("第" + str(i) + "次循环输出结果:\n" + str(arr))

    print("最终结果:\n" + str(arr))


insertion_sort([3, 1, 10, 7, 9, 6, 2])

结果:

1次循环输入数据:
[3, 1, 10, 7, 9, 6, 2]
中间过程========[3, 3, 10, 7, 9, 6, 2]1次循环输出结果:
[1, 3, 10, 7, 9, 6, 2]2次循环输入数据:
[1, 3, 10, 7, 9, 6, 2]2次循环输出结果:
[1, 3, 10, 7, 9, 6, 2]3次循环输入数据:
[1, 3, 10, 7, 9, 6, 2]
中间过程========[1, 3, 10, 10, 9, 6, 2]3次循环输出结果:
[1, 3, 7, 10, 9, 6, 2]4次循环输入数据:
[1, 3, 7, 10, 9, 6, 2]
中间过程========[1, 3, 7, 10, 10, 6, 2]4次循环输出结果:
[1, 3, 7, 9, 10, 6, 2]5次循环输入数据:
[1, 3, 7, 9, 10, 6, 2]
中间过程========[1, 3, 7, 9, 10, 10, 2]
中间过程========[1, 3, 7, 9, 9, 10, 2]
中间过程========[1, 3, 7, 7, 9, 10, 2]5次循环输出结果:
[1, 3, 6, 7, 9, 10, 2]6次循环输入数据:
[1, 3, 6, 7, 9, 10, 2]
中间过程========[1, 3, 6, 7, 9, 10, 10]
中间过程========[1, 3, 6, 7, 9, 9, 10]
中间过程========[1, 3, 6, 7, 7, 9, 10]
中间过程========[1, 3, 6, 6, 7, 9, 10]
中间过程========[1, 3, 3, 6, 7, 9, 10]6次循环输出结果:
[1, 2, 3, 6, 7, 9, 10]
最终结果:
[1, 2, 3, 6, 7, 9, 10]

5、归并排序

5.1、思想

来源:归并排序(Merge Sort)图解,归并排序算法-学到牛牛
归并排序是建立在归并操作上的一种有效、稳定的排序算法,该算法采用非常经典的分治法(分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化),归并排序的思路很简单,速度呢,也仅此于快速排序

基本思路:

第一步:将序列中待排序数字分为若干组,每个数字分为一组。

第二步:将若干组两两合并,保证合并的组都是有序的。

第三步:重复第二步的操作,直到剩下最后一组即为有序数列。

详细步骤:

首先将数组中待排序数字分成若干组,每个数字为一组
在这里插入图片描述
相邻的两组进行对比,并且两两合并,保证合并后都是有序的数列,i(数字8)> j(数字4)需要交换位置(最终呈现一个升序的数组),经过比较合并后两个数存入一个空的指针里
在这里插入图片描述
在这里插入图片描述
其他组按照此方法依次合并,从8个组合并成4个组
在这里插入图片描述
继续相邻的两个组进行合并
在这里插入图片描述
定义两个变量i,j分别代表P1里的第一个值(4)和P2里的第一个值(5),i和j进行比较,i < j(4 < 5),将数字4移入p中,i向后移动一位

在这里插入图片描述
i和j进行比较,i > j(8 > 5 ),将数字5移动到p中(4的后一位),j后移一位
在这里插入图片描述
i 和j继续进行比较,i > j (8 > 7),将数字7移动到p中(5的后一位),p2中没有待排序的数字,所以比较结束,p1中剩下的数字移动到p中(7的后一位),合并结束。旁边两个序列按照同样的方式进行合并,最后得到两个有序序列,将这两个有序序列通过上面的方式继续进行合并

在这里插入图片描述
i和j进行比较,i > j(4 > 1),i不动,p2中的数字1移动到p中,j向后移动一位
在这里插入图片描述
i继续和j比较,i > j(4 > 2),数字2移动到p中(1的后一位),j向后移动一位

在这里插入图片描述
i继续和j比较,i > j(4 > 3),数字3移动到p中(2的后一位),j向后移动一位

在这里插入图片描述
i继续和j比较,i < j(4 <6),数字4移动到p中(3的后一位),i向后移动一位
在这里插入图片描述
i继续和j比较,i > j(7 >6),数字6移动到p中(5的后一位),p2中已经没有待排序的数字,所以比较结束,p1中剩下的数字移动到p中(6的后面)
在这里插入图片描述
最后得到一个有序的数列 ,归并排序结束
在这里插入图片描述

5.2、代码

def merge_sort(arr):
    # 判断是否需要继续划分  
    if len(arr) <= 1:
        return arr

    # 将数组划分为左右两部分
    mid = len(arr) // 2
    left = arr[:mid]
    right = arr[mid:]

    # 递归地对左右两部分进行排序  
    left = merge_sort(left)
    right = merge_sort(right)

    # 合并左右两部分  
    return merge(left, right)


def merge(left, right):
    result = []  # 存储合并后的结果  
    i = j = 0  # i和j分别指向左右两部分的起始位置  
    while i < len(left) and j < len(right):
        # 如果左部分当前元素小于等于右部分当前元素,则将其加入结果列表  
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
            # 否则将右部分当前元素加入结果列表
        else:
            result.append(right[j])
            j += 1
            # 如果左部分还有剩余元素,将其加入结果列表
    while i < len(left):
        result.append(left[i])
        i += 1
        # 如果右部分还有剩余元素,将其加入结果列表
    while j < len(right):
        result.append(right[j])
        j += 1
    return result


if __name__ == '__main__':
    print(merge_sort([3, 11, 6, 2, 5, 8]))

6、二分查找

def binary_search(arr, left, right, target):
    if left > right:
        return '-1'

    mind = (left + right) // 2

    if target > arr[mind]:
        left = mind + 1
    elif target < arr[mind]:
        right = mind - 1
    elif target == arr[mind]:
        return mind
    else:
        return "-1"

    return binary_search(arr, left, right, target)


ll = [1, 2, 3, 5, 6, 8]
print(binary_search(ll, 0, len(ll)-1, 5))

7、二叉树遍历

class TreeNode:
    def __init__(self, value = None, left = None, right = None):
        self.value = value
        self.left = left
        self.right = right


def preTraverse(root):
    if root == None:
        return None

    print(root.value)
    preTraverse(root.left)
    preTraverse(root.right)


def mindTraverse(root):
    if root == None:
        return None

    mindTraverse(root.left)
    print(root.value)
    mindTraverse(root.right)

def afterTraverse(root):
    if root == None:
        return None

    afterTraverse(root.left)
    afterTraverse(root.right)
    print(root.value)


root = TreeNode('A', TreeNode('D', TreeNode('ld'), TreeNode('rd')), TreeNode('E', TreeNode('le'), TreeNode('re')))

print("前序遍历:\n")
preTraverse(root)
print("中序遍历:\n")
mindTraverse(root)
print("后序遍历:\n")
afterTraverse(root)

未完待续…

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

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

相关文章

机器人路径规划:基于Bug算法的机器人路径规划(提供Python代码)

一、Bug算法简介 Bug 算法是一种基于追踪障碍物的路径规划算法&#xff0c;它模拟了一种昆虫寻找巢穴的行为&#xff0c;因此得名Bug算法。Bug算法的基本思路是&#xff1a;当机器人遇到障碍物时&#xff0c;他会沿着障碍物的边缘行走&#xff0c;直到到达目标点。该算法可以分…

代码随想录算法训练营第二十五天|216.组合总和III,17.电话号码的字母组合

216.组合总和III 题目 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数&#xff0c;并且每种组合中不存在重复的数字。 说明&#xff1a; 所有数字都是正整数。 解集不能包含重复的组合。 示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 示例 2: 输入…

深入了解JVM底层原理

一、JVM内存结构 1、方法区&#xff1a;存储编译后的类、常量等&#xff08;.class字节码文件&#xff09; 2、堆内存&#xff1a;存储对象 3、程序计数器&#xff1a;存储当前执行的指令地址&#xff08;计算机处理器&#xff08;CPU&#xff09;正在执行的下一条指令在内存…

Java后端八股----JVM篇

上图中线程1&#xff0c;2如果资源被抢占了&#xff0c;则程序计数器记录一下执行的行号&#xff0c;等到资源就绪后会从记录的行号继续向后执行。 Java8把静态变量以及常量放到了线程的本地内存原空间中(避免放在堆中不可控)。 &#x1f446;图中第二种情况不太容易出现…

【Chapter1】操作系统概述,计算机操作系统教程,第四版,左万利,王英

文章目录 一、操作系统的基本概念1.1操作系统的层次结构1.2操作系统的运行视图1.3操作系统的概念(定义)1.4操作系统的功能和目标1.4.1操作系统的功能和目标——作为系统资源的管理者1.4.2操作系统的功能和目标——向上层提供方便易用的服务1.4.2.1GUI&#xff1a;图形化用户接口…

CPU vs. GPU :本质差异是?

他们的目的都是做并行计算的&#xff0c;但并行计算可分为时间上的并行和空间上的并行。所以我觉得本质差异是&#xff1a; CPU 时间并行GPU 空间并行 这样就容易理解他们的工作方式&#xff1a; 对CPU来说&#xff0c;不同的核心可以执行不同的机器指令但GPU则不同&#xff…

长安链开源社区发布2023年度长安链优秀应用案例

1月27日结束的“长安链发布三周年庆暨生态年会”上&#xff0c;在国家区块链技术创新中心的指导下&#xff0c;长安链开源社区联合长安链生态联盟正式发布2023年度长安链行业示范案例、领域精品案例及特色创新案例。 本次评选面向2023年度应用长安链上线并取得应用成效的案例&…

SSA优化最近邻分类预测(matlab代码)

SSA-最近邻分类预测matlab代码 麻雀搜索算法(Sparrow Search Algorithm, SSA)是一种新型的群智能优化算法&#xff0c;在2020年提出&#xff0c;主要是受麻雀的觅食行为和反捕食行为的启发。 数据为Excel分类数据集数据。 数据集划分为训练集、验证集、测试集,比例为8&#…

intelliJ配置Android环境 与 文件目录解释

实验目的与要求&#xff1a; 目的&#xff1a;掌握面向Android编程的开发环境搭建。学习、掌握Android程序编写基本步骤&#xff0c;例如&#xff0c;Android Studio平台编写简单的一个 HelloWorld程序&#xff0c;掌握编译、运行等基本步骤和操作。 内容要求&#xff1a; 搭建…

杂货铺 | vscode配置C/C++环境(亲测极简ver)

文章目录 &#x1f4da;Step1&#xff1a;下载安装VSCode&#x1f4da;Step2&#xff1a;下载安装g&#x1f4da;Step3&#xff1a;编辑环境变量&#x1f4da;Step4&#xff1a;安装vscode插件&#x1f4da;Step5&#xff1a;建好文件夹⭐️&#x1f4da;Step6&#xff1a;开始…

【Node.js从基础到高级运用】十三、NodeJS中间件高级应用

在现代web开发中&#xff0c;Node.js因其高效和灵活性而备受青睐。其中&#xff0c;中间件的概念是构建高效Node.js应用的关键。在这篇博客文章中&#xff0c;我们将深入探讨Node.js中间件的高级应用&#xff0c;包括创建自定义中间件、使用第三方中间件等。我们将从基础讲起&a…

qt vs 编程 字符编码 程序从源码到编译到显示过程中存在的字符编码及隐藏的字符编码转换

理解字符编码&#xff0c;请参考&#xff1a;unicode ucs2 utf16 utf8 ansi GBK GB2312 CSDN博客 了解windows字符显示必须了解locale概念 参考&#xff1a;揭密 Windows 上的各种 locale - 知乎 汉字&#xff08;或者说多字节字符&#xff09;的存放需求&#xff0c;是计算…

【CSP试题回顾】202309-2-坐标变换(其二)

CSP-202309-2-坐标变换&#xff08;其二&#xff09; 解题代码 #include <iostream> #include <vector> #include <cmath> #include <iomanip> using namespace std;struct MyOpt {double k, theta; }; int n, m, opt, s, e; double para, x, y;int …

Java项目:62 基于ssm的校园驿站管理系统+jsp

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 管理员管理快递仓库信息&#xff0c;管理待发货信息&#xff0c;管理已收快递&#xff0c;管理物流以及留言信息&#xff0c;管理员工和用户资料。 员…

C++——字符串、读写文件、结构体、枚举

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

【Java】高级篇1:异常处理

异常&#xff1a;程序在执行过程中出现的非正常情况&#xff0c;如果不处理最终会导致JVM的非正常停止。 Java的异常抛出机制 Java异常体系 1、Throwable 2、Error和Exception 异常处理方式 1、try-catch-finally&#xff08;捕获异常&#xff09; 基本结构&#xff1a; 使用…

B140XW01 V8 +OZ9956B PDF

B140XW01 V8 PDF OZ9956B 14B38-COW 18650串联50欧点亮一颗灯珠

代码随想录算法训练营第11天| 20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值

系列文章目录 目录 系列文章目录20. 有效的括号利用栈对称匹配将栈中元素弹出与判断栈顶元素是否匹配分开&#xff0c;比较耗时&#xff08;2ms)&#xff1a;若将栈中元素弹出与判断栈顶元素是否匹配放一起&#xff0c;比较节省时间(1ms)&#xff1a; 1047. 删除字符串中的所有…

探索区块链世界:从加密货币到去中心化应用

相信提到区块链&#xff0c;很多人会想到比特币这样的加密货币&#xff0c;但实际上&#xff0c;区块链技术远不止于此&#xff0c;它正在深刻地改变我们的生活和商业。 首先&#xff0c;让我们来简单了解一下什么是区块链。区块链是一种分布式数据库技术&#xff0c;它通过将…

MySQL的insert-on-duplicate语句详解

一、insert-on-duplicate语句语法 注意&#xff1a;ON DUPLICATE KEY UPDATE只是 MySQL的特有语法&#xff0c;并不是SQL标准语法&#xff01; INSERT INTO … ON DUPLICATE KEY UPDATE 是 MySQL 中一种用于插入数据并处理重复键冲突的语法。 这个语法适用于在 insert的时候…