强化历程7-排序算法(2023.9.12)

news2024/11/24 2:59:02
  • 此笔记学习图片来自于如下网址

1https://www.west999.com/info/html/chengxusheji/Javajishu/20190217/4612849.html

文章目录

  • 强化历程7-排序算法
    • 1 冒泡排序(交换排序)
    • 2 选择排序
    • 3 直接插入排序
    • 4 希尔排序
    • 5 归并排序
    • 6 快速排序
    • 7 堆排序
    • 8 计数排序

强化历程7-排序算法

1 冒泡排序(交换排序)

在这里插入图片描述

思想:每轮排序,相邻两个元素比较,如果后面元素小于前面元素,则位置颠倒;

  • 每轮可以确定一个最大值,下轮比较只需比较剩下的n-1个元素,排序结束后,退出循环。
    static int[] maopao(int[] arr) {
        int temp = 0;//交换位
        boolean flag = false;//标志位,记录有无交换
        //外层遍历控制遍历轮数
        for (int i = 0; i < arr.length - 1; i++) {
            flag = false; // 每轮排序开始时,将标志位重置为false
            //内层进行交换,并且下轮比较只需比较剩下的n-1个元素
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {//如果前面比后面大,交换位置
                    flag = true;
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            if (!flag){//如果没交换
                break;
            }
            System.out.print("第" + i + "轮交换结果为:");
            for (int k : arr) {
                System.out.print(k + " ");
            }
            System.out.println("");
        }
        return arr;
    }
  • 时间复杂度:O(N^2),在冒泡排序中,每个元素需要和其他元素进行比较,因此总共需要进行 N^2 次比较操作。
  • 空间复杂度:O(1) ,在冒泡排序中,只需要使用一个临时变量进行数值交换,因此空间复杂度为 O(1)。

2 选择排序

在这里插入图片描述

思想:每轮对未排序元素选择一个最小(或最大的)的标记,放到未排序元素的最左边(或最右边)

       static int[] xuanze(int[] arr) {
        int temp; //交换位
        for (int i =0;i< arr.length-1;i++){
            int minIndex = i;//最小值下标
            //遍历未排序部分并最小的值
            for (int j = i+1; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            // 将找到的最小值与未排序部分的第一个元素交换位置
            temp = arr[minIndex];
            arr[minIndex] = arr[i];
            arr[i] = temp;
        }
        return arr;
    }

改进思路:每轮找到未排序元素的最大值和最小值,将他们放到未排序元素两端

  • 时间复杂度:O(N^2)

  • 空间复杂度:O(1)

3 直接插入排序

在这里插入图片描述

思想:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置后;
  6. 重复步骤2~5。
    static int[] charu(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            //取出当前元素
            int currentNum = arr[i];
            int j = i - 1;  //定位当前元素
            //对于当前元素,让其从后往前扫描,找出正确位置
            while (j >= 0 && arr[j] > currentNum) {
                //比当前元素大的后移一位
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j+1] = currentNum; //将当前元素插入合适位置
        }
        return arr;
    }
  • 时间复杂度

    • 最坏情况:每次插入每个元素都要挪动一次:O(N^2)
    • 最好情况:O(N)

    越接近顺序时间复杂度越低,元素越少效率越高,因为交换少,因此Arrays.sort()底层length<47为插入排序

  • 空间复杂度:O(1)

4 希尔排序

在这里插入图片描述

思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,然后依次缩减增量(gap)再进行排序,直到增量为1时,进行最后一次直接插入排序。

  • 相当与改进的直接插入排序,只不过原来间隔为1,改为现在的gap了,减少比较和移动的次数,从而提高排序效率。
     static int[] xier(int[] arr) {
        //将元素分组
        //增量gap设置为n/2,这意味着我们将数组分成多个子序列,每个子序列包含相隔一个增量的元素。
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            //对分组进行插入排序
            for (int i = gap;i<arr.length;i++){
                int currentNum = arr[i];//当前元素
                int j =i; 
                while (j>=gap&&arr[j-gap]>currentNum){
                    // 将比当前元素大的元素向右移动一个增量
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                // 将当前元素插入到正确的位置
                arr[j] = currentNum;
            }
        }
        return arr;
    }
  • 时间复杂度:O(NlogN)
  • 空间复杂度:O(1)

5 归并排序

在这里插入图片描述

思想:归并排序的思想是将待排序序列分成若干个子序列,每个子序列都是有序的。然后,将这些有序的子序列合并成一个整体有序的序列。

  • 思路: 不停递归分解数组,当分解到自己则退出

    然后开始合并排序

public class guibing {
    static void guibingGroup(int[] arr, int left, int right) {
        //递归,相遇时退出,也就是分解遇到自己
        if (left >= right) {
            return;
        }
        //获取中间元素
        int mid = (left + right)/2;
        guibingGroup(arr, left, mid); //左边序列
        guibingGroup(arr, mid + 1, right);//右边序列
        //合并
        guibingheBing(arr, left, mid, right);
    }
    private static void guibingheBing(int[] arr, int left, int mid, int right) {
        int s1 = left;//归并左边第一个数据
        int s2 = mid + 1;//归并右边第一个数据
        int temp[] = new int[right - left + 1];
        int index = 0;//表示temp数组下标
        while (s1 <= mid && s2 <= right) {//两边都不为空
            //比较s1和s2的值
            if (arr[s1] <= arr[s2]) {
                //放到数组后,下个数字
                temp[index++] = arr[s1++];
            } else {
                temp[index++] = arr[s2++];
            }
        }
        while (s1 <= mid) {
            temp[index++] = arr[s1++];
        }
        while (s2 <= right) {
            temp[index++] = arr[s2++];
        }
        for (int  i=0;i< temp.length;i++){
            //右边元素放到自己的位置
            arr[i+left] = temp[i];
        }
    }
}
  • 时间复杂度 Nlog(NlogN)
  • 空间复杂度O(N)

6 快速排序

在这里插入图片描述

思想:从左边(或者右边)找一个基准数。

然后从两边开始检索,( 如果左边为基准数从右开始检索,如果右边为基准数从左边开始检索),一边检索出比基准数小的,另一边检索比基准数大的。

如果检索到就停下,然后交换这两个元素,然后再继续检索。

这两个元素一旦相遇则停止检索,把基准数和相遇位置的元素交换。(第一轮结束):左边元素都比基准数小,右边元素都比基准数大。。。

    private static void kuaipai(int[] arr, int left, int right) {
        //左边索引大于右边,直接返回
        if (left >= right) {
            return;
        }
        int base = arr[left];//基准数
        int i = left;//指向左边元素
        int j = right;//指向右边元素
        //i和j不相遇
        while (i != j) {
            //先由j从右往左检索比基准数小的,如果检索到比基准数小停止
            while (arr[j] >= base && i < j) {
                j--;
            }
            //先由i从左往右检索比基准数大的,如果检索到比基准数大停止
            while (arr[i] <= base && i < j) {
                i++;
            }
            //找到了对于数组,交换i和j位置的元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        //如果上述条件不成立,i和j相遇
        arr[left] = arr[i];
        arr[i] = base;
        //基准数在这里归位
        //排基准数左面
        kuaipai(arr,left,i-1);
        //排右边
        kuaipai(arr,j+1,right);
    }

7 堆排序

在这里插入图片描述

  • 下标为i的节点的父节点下标: (i- 1)/2

  • 下标为i的节点的左孩子下标:i*2+1

  • 下标为i的节点的右孩子下标:i*2+2

思想:子节点要小于父节点

    private static void duipai(int[] tree, int current, int length) {
        int left = 2 * current + 1; //左节点索引
        int right = 2 * current + 2;//右节点索引
        int maxIndex = current; //最大节点索引
        // 左节点大于最大值
        if (left < length && tree[left] > tree[maxIndex]) {
            maxIndex = left;
        }
        // 右节点大于最大值
        if (right < length && tree[right] > tree[maxIndex]) {
            maxIndex = right;
        }
        // 如果当前索引和最大索引不相等
        if (current != maxIndex) {
            int temp = tree[current];
            tree[current] = tree[maxIndex];
            tree[maxIndex] = temp;
            duipai(tree,maxIndex,length);
        }
    }

将任意树调整为大顶堆

从倒数第一个非叶子结点开始,从后往前,按下标,依次作为根去向下调整即可。

  	//构建大顶堆
    private static void buildMaxHeap(int[] tree){
        int lastNode = tree.length-1;
        int parent = (lastNode-1)/2;
        for (int k= parent;k>=0;k--){
            duipai(tree,k);
        }
    }

排序

重新构建大顶堆

private static void duiSort(int[] arr){  
    //重新构建大顶堆  
    buildMaxHeap(arr);  
    for (int i=arr.length-1;i>=0;i--){  
        //最大值放到数组最后  
        int temp = arr[0];  
        arr[0] = arr[i];  
        arr[i] = temp;  
        //将最大值砍掉  
        duipai(arr,0,i);  
        // 重新调整堆  
        if (i != 0) {  
            duipai(arr, 0, i);  
        }  
    } 

8 计数排序

在这里插入图片描述

思想:它的基本思想是通过计算各个数值出现的次数,然后根据这些次数重新组织待排序数组,从而实现排序。

   public static void jishu(int[] array) {
            //找出数组中的最大值
            int max = array[0];
            for (int i = 1; i < array.length; i++) {
                if (array[i] > max) {
                    max = array[i];
                }
            }
            //初始化计数数组
            int[] countArray = new int[max + 1];

            //统计每个元素的出现次数
            for (int i = 0; i < array.length; i++) {
                countArray[array[i]]++;
            }
            //重新生成排序后的数组
            int index = 0;
            for (int i = 0; i < countArray.length; i++) {
                while (countArray[i] > 0) {
                    array[index++] = i;
                    countArray[i]--;
                }
            }
        }

  1. 1 ↩︎

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

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

相关文章

《向量数据库指南》——向量数据库内核面临的技术挑战及应对措施

最近一年&#xff0c;以 ChatGPT、LLaMA 为代表的大语言模型的兴起&#xff0c;将向量数据库的发展推向了新的高度。 向量数据库是一种在机器学习和人工智能领域日益流行的新型数据库&#xff0c;它能够帮助支持基于神经网络而不是关键字的新型搜索引擎。向量数据库不同于传统的…

6.1、Flink数据写入到文件

1、前言 Flink API 提供了FileSink连接器&#xff0c;来帮助我们将数据写出到文件系统中去 版本说明&#xff1a;java1.8、flink1.17 官网链接&#xff1a;官网 2、Format Types - 指定文件格式 FileSink 支持 Row-encoded 、Bulk-encoded 两种格式写入文件系统 Row-encode…

小程序自定义tabbar

前言 使用小程序默认的tabbar可以满足常规开发&#xff0c;但是满足不了个性化需求&#xff0c;如果想个性化开发就需要用到自定义tabbar,以下图为例子 一、在app.json配置 先按照以往默认的形式配置&#xff0c;如果中间的样式特殊则不需要配置 "tabBar": {&qu…

SpringWeb解析

目录 运行流程 组件介绍 简单搭建一个SpringWeb项目 1.导入依赖 2.配置DispatcherServlet 3.开启注解 4.处理器搭建 5.接收请求 获取请求的数据 中文乱码 返回json格式 拦截器 代码实现 SpringWeb 是 spring 框架中的一个模块&#xff0c;基于 Servlet API 构建的原…

豆瓣图书评分数据的可视化分析

导语 豆瓣是一个提供图书、电影、音乐等文化产品的社区平台&#xff0c;用户可以在上面发表自己的评价和评论&#xff0c;形成一个丰富的文化数据库。本文将介绍如何使用爬虫技术获取豆瓣图书的评分数据&#xff0c;并进行可视化分析&#xff0c;探索不同类型、不同年代、不同…

如何做好医药产品说明书翻译?

近年来&#xff0c;随着世界各国之间的交流日渐紧密&#xff0c;医药产业发达国家的药品和医用器械对于其他国家的输出日益增多&#xff0c;但这些医疗产品在流通过程中&#xff0c;往往需要专业的医药翻译人员进行产品说明书的精确翻译。那么&#xff0c;如何做好医药产品说明…

掌动智能:提升硬件连通性测试效率与精确度

在当今数字化时代&#xff0c;各种智能设备和硬件组件在我们的日常生活和工作中扮演着越来越重要的角色。为确保这些设备正常运行&#xff0c;并实现跨设备的无缝连接&#xff0c;硬件连通性测试变得至关重要。为了提高测试效率与精确度&#xff0c;让我们介绍掌动智能作为一家…

物理层(408)

一、通信基础 【2009】在无噪声的情况下&#xff0c;若某通信链路的带宽为3kHz&#xff0c;采用4个相位&#xff0c;每个相位具有4种振幅的QAM调制技术&#xff0c;则该通信链路的最大数据传输速率是&#xff08;B&#xff09; A、12kb/s B、24kb/s C、48kb/s …

A股风格因子看板 (2023.09 第01期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格暴 露等。 今日为该因子跟踪第1期&#xff0c;指数组合数据截止日2023-08-31&#xff0c;要点如下 近1年A股风格因子收益走…

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

DevOps实践指南 Part 4 第二步 &#xff1a;反馈的技术实践14. 建立能发现并解决问题的遥测系统14.1 建设集中式监控架构14.2 建立生产环境的应用程序日志遥测14.3 使用遥测指导问题的解决14.4 将建立生产遥测融入日常工作14.5 建立自助访问的遥测和信息辐射器14.6 发现和填补遥…

元宇宙全球市场规模到2030年将达9805亿美元!

元宇宙是一种新兴的概念&#xff0c;它指的是一个虚拟的世界&#xff0c;由人工智能、虚拟现实、区块链等技术构建而成。元宇宙的起源可以追溯到上世纪90年代的虚拟世界“第二人生”&#xff0c;但直到近年来&#xff0c;随着技术的不断发展&#xff0c;它才逐渐成为了人们关注…

labelme2voc 标签重叠/覆盖问题

使用labelme自带的 labelme2voc.py转换voc数据集时可能标签重叠

C语言实现单链表和双向循环链表

全文目录 链表单链表实现申请节点头插尾插头删尾删任意节点后插入删除单链表的销毁 带头双向循环链表实现链表初始化申请节点头插尾插头删尾删任意节点后插入删除链表的销毁 链表和顺序表对比总结 链表 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&…

GO语言篇之发布开源软件包

GO语言篇之发布开源软件包 文章目录 GO语言篇之发布开源软件包新建仓库拉取到本地初始化项目编写代码提交代码发布引用软件包 我们写GO语言程序的时候难免会引用第三方的软件包&#xff0c;那么你知道别人是怎么发布自己的软件包吗&#xff0c;别急&#xff0c;这篇博客教你怎么…

Apache DolphinScheduler 如何实现自动化打包+单机/集群部署?

Apache DolphinScheduler 是一款开源的分布式任务调度系统&#xff0c;旨在帮助用户实现复杂任务的自动化调度和管理。DolphinScheduler 支持多种任务类型&#xff0c;可以在单机或集群环境下运行。下面将介绍如何实现 DolphinScheduler 的自动化打包和单机/集群部署。 自动化…

【Oracle】数据库导入导出

Oracle数据库导入导出 文章目录 Oracle数据库导入导出一、expdp导出1、管理员身份登录2、删除以前测试的用户及对应的数据3、创建表空间&#xff08;源表--待导出的表&#xff09;4、创建用户&#xff0c;给用户设置默认表空间和临时表空间5、给用户授权&#xff08;创建表和视…

Unity+百度文心大模型驱动AI小姐姐数字人

1.简述 最近看到新闻&#xff0c;说是百度、字节、商汤、百川、智普等几家企业及机构所发布的生成式大语言模型&#xff0c;通过了《生成式人工智能服务管理暂行办法》&#xff0c;成为首批获得官方备案的大语言模型服务提供商。虽然一直在使用包括文心一言、chatglm这些大语言…

怒赞了,阿里P8面试官推荐的Java高并发核心编程文档

前言 学完阿里P8面试官推荐的Java高并发核心编程文档后&#xff0c;终于拿到了蚂蚁p6的offer&#xff0c;这份文档包含的内容有点多。 Java高并发核心编程文档《尼恩Java高并发三部曲》获读者怒赞&#xff01;获取方式见文末 文章目录 前言尼恩Java高并发三部曲卷1&#xff1…

适合引流的运动步数打卡抽奖小程序源码开发

要健康也要瘦&#xff1f;那么有一个可以让你悄悄改变还可以获取奖品的小程序简直不要太入心。用运动步数兑换奖品&#xff0c;每天运动一下&#xff0c;换点小礼品&#xff0c;简直不要太惬意。 运动步数兑换小程序核心亮点&#xff1a; 小程序与微信运动做了关联&#xff…

Android环境配置笔记

文章目录 一、各环境文档二、参考 一、各环境文档 Gradle官方的兼容性文档&#xff1a;Java Compatibility 更新日期&#xff1a;2023.9.12 Android Gradle插件版本&#xff1a;Android Gradle Plugin 二、参考 参考文章&#xff1a;Android问题记录