图解算法--排序算法

news2024/11/24 7:42:37

目录

1.冒泡排序算法

2.选择排序算法

3.插入排序算法

4.希尔排序算法

5.归并排序算法

6.快速排序算法


1.冒泡排序算法

原理讲解:

  1. 从待排序的数组中的第一个元素开始,依次比较当前元素和它相邻的下一个元素的大小。
  2. 如果当前元素大于相邻元素,则交换这两个元素的位置,将较大的元素向后冒泡。
  3. 继续比较相邻元素,重复以上步骤,直到遍历完整个数组。
  4. 一轮遍历完成后,最大的元素将会排在最后面。
  5. 重复执行上述步骤,每次遍历都将会使待排序的元素中最大的元素冒泡到正确的位置,直到所有元素都有序排列。

 传统的冒泡排序算法

package Sort.Bubble;

import java.util.Arrays;

public class javaDemo {
    public static void main(String[] args) {
        int nums[] = new int[]{1,4,36,7,42,2,12,5,2};
        int temp;
//        冒泡算法
        for (int i=0;i< nums.length-1;i++){
            for (int j=0;j< nums.length-i-1;j++){
                if (nums[j]>nums[j+1]){
                    temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(nums));
    }
}

传统的排序算法有个缺点,那就是不管数据是否已经完成排序都会固定执行n(n-1)/2次,而如果加入岗哨的概念进行改造冒泡排序算法就可以提高程序的执行效率

传统冒泡执行已经快要排序好的数组结果如下:

可以看到在第二轮时候就已经排序好了,但是还是不断进行遍历,所以加入一个岗哨(flag)判断功能,当第三轮时候,如果没有元素进行交换后直接退出排序 。

改进型冒泡排序法

package Sort.Bubble;

import java.util.Arrays;

public class Sentry {
    public static void main(String[] args) {
        int num[] = new int[]{1,4,5,2,7,8,9};
        int flag;
        int temp;
        for (int i= num.length-1;i>0;i--){
            flag = 0;
//            如果发生了交换则不跳出
            for (int j=0;j<i-1;j++){
                if (num[j]>num[j+1]){
                 temp = num[j];
                 num[j] = num[j+1];
                 num[j+1] = temp;
                 flag ++;
                }
            }
//            如果从头遍历结束都没有交换则直接退出
            if (flag == 0){
                break;
            }
            System.out.println("第"+(num.length-i)+"轮排序结果为"+ Arrays.toString(num));
        }
    }
}

 算法分析:

  • 冒泡排序算法在最坏的情况下时间复杂度是O(n^2)
  • 在最好的情况下时间复杂度是O(n)

2.选择排序算法

原理讲解: 

  1. 遍历待排序的数组,将第一个元素作为当前最小值。
  2. 从当前位置之后的元素中找到最小的元素,并记录其位置。
  3. 如果找到了比当前最小值更小的元素,则将该元素的位置更新为当前最小值的位置。
  4. 遍历完整个数组后,将最小值与当前位置的元素进行交换。
  5. 继续从下一个位置开始重复以上步骤,直到遍历完整个数组。

案例代码

package Sort.Chose.chose;

import java.util.Arrays;

public class javaDemo {
    public static void main(String[] args) {
        int nums[] = new int[]{1,2,4,2,3,51,12,6,2};
        int min;
        int index;
        int temp;
        for (int i=0;i< nums.length-1;i++){
//            每一轮初始化最小值与最小值下角标
            min = nums[i];
            index = i;
            for (int j=i+1;j< nums.length;j++){
                if (min>nums[j]){
                    min = nums[j];
                    index = j;
                }
            }
             temp = nums[i];
            nums[i] = min;
            nums[index] = temp;
        }
        System.out.println(Arrays.toString(nums));
    }
}

 算法分析:

  • 冒泡排序算法无论在最坏还是最好的情况下时间复杂度都是O(n^2)

3.插入排序算法

 原理讲解:

  1. 将数组分为已排序和未排序两部分。一开始,将第一个元素视为已排序部分,其余元素视为未排序部分。
  2. 从未排序部分选择第一个元素,依次与已排序部分的元素比较。
  3. 如果选取的元素小于已排序部分的某个元素,则将该元素插入到正确的位置,同时将已排序部分中的元素向后移动一位。
  4. 重复上述步骤,将未排序部分的每个元素逐个插入到已排序部分的正确位置。
  5. 当所有元素都插入完成,即未排序部分为空时,排序完成。

案例代码  

package Sort.InsertSort;

import java.util.Arrays;

public class javaDemo {
    public static void main(String[] args) {
        int nums[] = new int[]{4,1,5,2,6,7,2};
        int temp;
        for (int i=0;i< nums.length;i++){
            for (int j=0;j<i;j++){
                if (nums[i]<nums[j]){
                    temp = nums[j];
                    nums[j] = nums[i];
                    nums[i] = temp;
                }
            }
            System.out.println("第"+(i+1)+"轮排序结果为"+ Arrays.toString(nums));
        }
    }
}

算法分析:

  • 冒泡排序算法在最坏的情况下时间复杂度是O(n^2)
  • 在最好的情况下时间复杂度是O(n)

4.希尔排序算法

  原理讲解:

  1. 首先,选择一个增量 gap,通常将数组长度的一半作为初始增量。
  2. 将数组按照增量进行分组,并对每个分组使用插入排序算法进行排序。
  3. 逐渐缩小增量,重复以上步骤,直到增量为 1。
  4. 最后使用增量为 1 的插入排序对整个数组进行最后一次排序

案例代码:

package Sort.Shell;

import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {9, 5, 2, 7, 1, 8, 3, 6, 4};
        int n = arr.length;

        // 定义增量序列
        int[] increments = {5, 3, 1};
        System.out.println("原始数组顺序为"+Arrays.toString(arr));
        // 遍历增量序列
        for (int increment : increments) {

            // 对每个增量进行插入排序
            for (int i = increment; i < n; i++) {
                int temp = arr[i];
                int j = i;
                // 在当前增量下,对子序列进行插入排序
                while (j >= increment && arr[j - increment] > temp) {
                    arr[j] = arr[j - increment];
                    j -= increment;
                }
                arr[j] = temp;
                System.out.println("当前增量为"+increment+",当前数组为:"+Arrays.toString(arr));
            }

        }
    }
}

算法分析:

  • 希尔排序算法无论在最坏还是最好的情况下时间复杂度都是O(n^3/2)
  • 空间最优解

5.归并排序算法

   原理讲解:

  1. 将待排序的数组递归地分成两个子数组,直到每个子数组只有一个元素。
  2. 对每个子数组进行合并操作,将两个有序的子数组合并成一个有序的数组。
  3. 重复以上步骤,直到所有的子数组都被合并成一个完整的有序数组。

案例代码:

package Sort.MergeSort;

import java.util.Arrays;

public class mergeSort {
    public static void mergeSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
    }

    private static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = left + (right - left) / 2;
            mergeSort(arr, left, mid, temp); // 递归排序左半部分
            mergeSort(arr, mid + 1, right, temp); // 递归排序右半部分
            merge(arr, left, mid, right, temp); // 合并左右两个有序数组
        }
        System.out.println("当前顺序为"+Arrays.toString(arr));
    }

    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left; // 左半部分起始索引
        int j = mid + 1; // 右半部分起始索引
        int k = 0; // 临时数组索引

        // 将左右两个有序数组按顺序合并到temp数组中
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }

        // 处理剩余的元素
        while (i <= mid) {
            temp[k++] = arr[i++];
        }
        while (j <= right) {
            temp[k++] = arr[j++];
        }

        // 将临时数组的元素拷贝回原数组
        for (i = 0; i < k; i++) {
            arr[left + i] = temp[i];
        }
    }
    public static void main(String[] args) {
        int[] arr = {9, 5, 2, 7, 1, 8, 3, 6, 4};
        System.out.println("原始数组:"+ Arrays.toString(arr));
        mergeSort(arr);
    }
}

算法分析:

  • 归并排序算法无论在最坏还是最好的情况下时间复杂度都是O(nlogn)

6.快速排序算法

   原理讲解:

  1. 选择一个基准元素(通常是数组的第一个或最后一个元素)作为参考点。
  2. 将待排序的数组分成两个子数组,其中一个子数组中的元素小于等于基准元素,另一个子数组中的元素大于基准元素。
  3. 对这两个子数组分别重复上述步骤,递归地进行快速排序。
  4. 当子数组的长度为 1 或 0 时,递归终止。
  5. 将排序好的子数组合并起来,即可得到完整的有序数组。

案例代码:

package Sort.Quick;

import java.util.Arrays;

public class QuickSort {
    public static void quickSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }

    private static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pivotIndex = partition(arr, low, high); // 将数组划分为两部分,返回中轴元素的索引
            quickSort(arr, low, pivotIndex - 1); // 递归排序左半部分
            quickSort(arr, pivotIndex + 1, high); // 递归排序右半部分
        }
        System.out.println("当前数组为"+Arrays.toString(arr));
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[low]; // 选择第一个元素作为中轴元素
        int left = low;
        int right = high;

        while (left < right) {
            // 从右向左找第一个小于等于中轴元素的位置
            while (left < right && arr[right] >= pivot) {
                right--;
            }
            if (left < right) {
                arr[left] = arr[right];
                left++;
            }

            // 从左向右找第一个大于中轴元素的位置
            while (left < right && arr[left] <= pivot) {
                left++;
            }
            if (left < right) {
                arr[right] = arr[left];
                right--;
            }
        }

        arr[left] = pivot; // 将中轴元素放置到最终位置
        return left; // 返回中轴元素的索引
    }

    public static void main(String[] args) {
        int[] arr = {9, 5, 2, 7, 1, 8, 3, 6, 4};

        System.out.printf("原始数组:");
        System.out.println(Arrays.toString(arr));
        quickSort(arr);
    }
}

 算法分析:

  • 快速排序算法在最坏的情况下时间复杂度是O(nlog2n)
  • 在最好的情况下时间复杂度是O(n)
  • 公认最好的排序算法

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

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

相关文章

7. 实现 API 自动生成

目录 1. pom.xml中引用依赖 2. 引入相关的依赖 3. 编写配置类 4. application.yml 中添加配置 5. API 常用注解 6. 访问 API 列表 7. API 导入 Postman 使用 Springfox Swagger生成 API&#xff0c;并导入 Postman&#xff0c;完成API单元测试。 Swagger 简介&#xff1a;Swag…

记录一个编译TubeTK时的报错:at_check问题

在使用如下命令安装TubeTK的cuda_nms时&#xff0c;报了一个错误&#xff0c;记录一下这个错误和解决办法 (base) redmeryredmery:~/Desktop/MOT/TubeTK/post_processing/nms$ python setup.py build_ext --inplace因为这个命令是在/home/redmery/Desktop/MOT/TubeTK/install/…

途乐证券-炒股开户流程是怎样的?

炒股是一种危险较大但收益也相对较高的出资方法&#xff0c;而开户则是出资炒股的前提。跟着科技的开展&#xff0c;炒股开户已经能够在线完结&#xff0c;但流程相对来说仍是比较繁琐的。那么&#xff0c;炒股开户流程是怎样的呢&#xff1f;下面从多个视点剖析。 一、炒股开户…

基于Servlet实现的管理系统(包含服务器源码+数据库)

资料下载链接 介绍 基于Servlet框架的管理系统 简洁版 &#xff1b; 实现 登录 、 注册 、 增 、 删 、 改 、 查 &#xff1b; 可继续完善增加前端、校验、其他功能等&#xff1b; 可作为 Servlet项目 开发练习基础模型&#xff1b; 课程设计 、 毕业设计 开发基础&…

PublicDNS服务提供商增加字节,将支持 DoH/DoT/DoQ 等协议

随着互联网的发展&#xff0c;网页的复杂程度也在增加。客户端在访问一个网页时&#xff0c;通常需要发送数十个 DNS 查询请求才能完整加载一个网页的全部资源。在这种情况下&#xff0c;DNS 解析的速度和准确率会影响网页的加载速度。 公共解析 PublicDNS 向用户提供 DNS 服务…

Android Studio导入项目需要做的一些配置

点击项目结构 选择本地安装的SDK、NDK目录 选择java版本 重新加载项目 Clean Project Rebuild Project 选择要构建的版本 可选debug和release 打包apk安装包 打包完成&#xff0c;就可以安装到安卓手机了

c语言——连接字符串

//连接字符串 #include<stdio.h> #include<stdlib.h> int main() {char s1[100],s2[100],i,j;printf("第一个字符串&#xff1a;");scanf("%s",s1);printf("第二个字符串&#xff1a;");scanf("%s",s2);for(i0;s1[i]!\0;i…

Android开发之性能优化:过渡绘制解决方案

1. 过渡绘制 屏幕上某一像素点在一帧中被重复绘制多次&#xff0c;就是过渡绘制。 下图中多个卡片跌在一起&#xff0c;但是只有第一个卡片是完全可见的。背后的卡片只有部分可见。但是Android系统在绘制时会将下层的卡片进行绘制&#xff0c;接着再将上层的卡片进行绘制。但其…

AgentBench:再谈何谓AI智能体?

除了具有完成特殊任务所需要的技能之外,AI智能体还可以根据人们的需要,训练出特别的个性。用过ChatGPT的读者应该都知道,虽然ChatGPT可以和我们流畅地进行交流,并且随着交流的深入,它可以根据用户的特点,在表述风格和习惯上作出一定的调整,但是从总体上看,它依然是沉闷…

vue 使用indexDB 简单完整逻辑

1 npm npm install idb 2 代码 <template><div><p>Data: {{ data }}</p><button click"fetchData">Fetch Data</button></div> </template><script> import { openDB } from idb;export default {data() {…

sid=‘*‘和sid=‘orcl1‘的区别--实战问题

客户有个11g rac环境&#xff0c;前一段时间db1内存故障了&#xff0c;更换后需要调整db1的sga和pga&#xff0c;操作如下 SQL> alter system set sga_target25G scopespfile sid*; System altered. SQL> alter system set sga_max_size25G scopespfile sid*; Syste…

flowable流程部署只生成了act_re_deployment,未生成act_re_procdef

绘制的流程图 使用错误检测功能 没有检测到错误 下载后重名vacation.bpmn201.xml部署。 /*** 流程部署*/Testpublic void testDeploy() {//1.获取ProcessEngine对象ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();//2、获取RepositoryServiceReposi…

【面试高频题】难度 3/5,字典树热门运用题

题目描述 这是 LeetCode 上的 「745. 前缀和后缀搜索」 &#xff0c;难度为 「困难」。 Tag : 「字典树」 设计一个包含一些单词的特殊词典&#xff0c;并能够通过前缀和后缀来检索单词。 实现 WordFilter 类&#xff1a; WordFilter(string[] words) 使用词典中的单词 words 初…

PyTorch学习笔记(十三)——现有网络模型的使用及修改

以分类模型的VGG为例 vgg16_false torchvision.models.vgg16(weightsFalse) vgg16_true torchvision.models.vgg16(weightsTrue) print(vgg16_true) vgg16_true.classifier.add_module("add_linear",nn.Linear(1000,10)) print(vgg16_true) vgg16_false.classifie…

mysql的快速复习 和一些思考记录

数据库设计 第一范式&#xff1a;有主键&#xff0c;具有原子性&#xff0c;字段不可分割 数据库表中不能出现重复记录&#xff0c;每个字段是原子性的不能再分 关于第一范式&#xff0c;每一行必须唯一&#xff0c;也就是每个表必须有主键。 每一列不可再分&#xff01;&#…

C++之ostream与ifstream读写文件操作(一百八十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

「2024」预备研究生mem-论证推理强化:引入前提(下)

一、论证推理强化&#xff1a;引入前提&#xff08;下&#xff09; 二、课后题

基于JAVA的仓库管理系统java库房仓储进销存jsp源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 基于JAVA的仓库管理系统 系统有2权限&#xff1a;用户…

医院智慧配电能效平台系统的建设与实践

摘 要&#xff1a;为降低医院建筑能耗&#xff0c;通过将精细化管理引入医院建筑能源系统&#xff0c;细化分析医院能耗特点和能源管理流程&#xff0c;设计决策过程和构建评价标准&#xff0c;形成能源系统精细化管理体系。以广州市番禺中心医院为例&#xff0c;通过建立能效评…

【JavaScript】使用js实现滑块验证码功能与浏览器打印

滑块验证码 效果图&#xff1a; 实现思路&#xff1a; 根据滑块的最左侧点跟最右侧点&#xff0c; 是否在规定的距离内【页面最左侧为原点】&#xff0c;来判断是否通过 html代码&#xff1a; <!DOCTYPE html> <html><head><title>滑动图片验证码&…