数据结构和算法解析:排序问题简易总结

直接插入排序
直接插入排序(Straight Insertion Sorting)的基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
直接插入排序是一种稳定的排序方法,最好的时间复杂是O(n)也就是已经排好的序列,最差的时间复杂度是O(n^2)逆序

    //插入排序是一种稳定的排序方法,最好的时间复杂是O(n)也就是已经排好的序列,最差的时间复杂度是O(n^2)逆序
    public void insertSort(int nums[]){
        int tmp;
        for(int i=1;i<nums.length;i++){
            int j=i;
            while (j>0 && nums[j]<nums[j-1]){
                tmp=nums[j];
                nums[j]=nums[j-1];
                nums[j-1]=tmp;
                j--;
            }
        }
    }

希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
算法思想
对于直接插入排序问题,数据量巨大时。将数的个数设为n,取奇数k=n/2,将下标差值为k的数分为一组,构成有序序列。再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。重复第二步,直到k=1执行简单插入排序。

希尔排序是一种非常不稳定的排序方法,它的时间复杂度为O(n^(1.3—2))

//希尔排序是一个不稳定的排序算法,它的时间复杂度为O(n^(1.3—2))
    public void shellSortHelper(int nums[],int incr){
        int tmp;
        for(int i=incr;i<nums.length;i+=incr){
            int j=i;
            while (j>0 && nums[j]<nums[j-incr]){
                tmp=nums[j];
                nums[j]=nums[j-incr];
                nums[j-incr]=tmp;
                j-=incr;
            }
        }
    }
    //希尔排序
    public void shellSort(int nums[]){
        for(int i=nums.length/2;i > 0;i/=2){
            shellSortHelper(nums,i);
        }
    }


选择排序
常用于取序列中最大最小的几个数时。
(如果每次比较都交换,那么就是交换排序;如果每次比较完一个循环再交换,就是简单选择排序。)

遍历整个序列,将最小的数放在最前面。

遍历剩下的序列,将最小的数放在最前面。

重复第二步,直到只剩下一个数。

选择排序的时间复杂度为O(n^2) 选择排序不是一个稳定的排序

//交换排序是一种稳定的排序方法,最好最坏的时间复杂度都是O(n^2)
    public void swapSort(int nums[])
    {
        int tmp;
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                if(nums[i]>nums[j]){
                    tmp=nums[j];
                    nums[j]=nums[i];
                    nums[i]=tmp;
                }
            }
        }
    }

    //选择排序是一种不稳定的排序方法,最好最坏的时间复杂度都是O(n^2)
    public void selectSort(int nums[]){
        for(int i=0;i<nums.length;i++){
            int values=nums[i];
            int position=i;
            for(int j=i+1;j<nums.length;j++){
                if(nums[j]<values){
                    values=nums[j];
                    position=j;
                }
            }
            //swap
            nums[position]=nums[i];
            nums[i]=values;
        }
 
冒泡排序
很简单,用到的很少,据了解,面试的时候问的比较多!将序列中所有元素两两比较,将最大的放在最后面。将剩余序列中所有元素两两比较,将最大的放在最后面。重复第二步,直到只剩下一个数。

冒泡排序的时间复杂度为O(n^2) 冒泡排序是一个稳定的排序

    //冒泡排序 一种稳定的排序算法,最好最坏的时间复杂度都是O(n^2)
  public void bubbleSort(int nums[]){
        int tmp;
        for(int i=0;i<nums.length;i++){
            for (int j=0;j<nums.length-i-1;j++){
                if(nums[j]>nums[j+1]){
                    tmp=nums[j+1];
                    nums[j+1]=nums[j];
                    nums[j]=tmp;
                }
            }
        }
  }

快速排序
要求时间最快时。

选择第一个数为p,小于p的数放在左边,大于p的数放在右边。
递归的将p左边和右边的数都按照第一步进行,直到不能递归。
快速排序是由一种不稳定的排序算法,最好的时间复杂度是O(nLogN),最差时间复杂度是O(n^2)

 //快速排序是由一种不稳定的排序算法,最好的时间复杂度是O(nLogN),最差时间复杂度是O(n^2)
    private void quickSortHelper(int nums[],int start,int end){
      if(start>end) return;
      int high=end;
      int low=start;
      int target=nums[start];
      while (low<high){
          while (low<high && nums[high]>=target){
              high--;
          }
          nums[low]=nums[high];
          while (low<high && nums[low]<=target){
              low++;
          }
          nums[high]=nums[low];
      }
      nums[low]=target;
      quickSortHelper(nums,start,low-1);
      quickSortHelper(nums,low+1,end);
    }

    public void quickSort(int nums[])
    {
        quickSortHelper(nums,0,nums.length-1);
    }



归并排序
速度仅次于快速排序,内存少的时候使用,可以进行并行计算的时候使用。

选择相邻两个数组成一个有序序列。
选择相邻的两个有序序列组成一个有序序列。重复第二步,直到全部组成一个有序序列。
归并排序,是一种稳定的排序是算法这个算法的时间复复杂度都是O(NlogN)

    //归并排序,是一种稳定的排序是算法这个算法的时间复复杂度都是O(NlogN)
    public void mergeSrot(int nums[],int start,int end){
        if(start>=end) return;
        int mid=(start+end)/2;
        mergeSrot(nums,start,mid);
        mergeSrot(nums,mid+1,end);
        mergeSrotHelper(nums,start,mid,end);
    }
        //  将两个有序序列归并为一个有序序列(二路归并)
    private void mergeSrotHelper(int[] nums, int start, int mid, int end) {
        int[] arr=new int[end+1];
        int low=start;

        int left=start;
        int center=mid+1;

        while (left<=mid && center<=end){
            arr[low++] = nums[left] <= nums[center] ? nums[left++] : nums[center++];
        }

        while (left<=mid){
            arr[low++]=nums[left++];
        }
        while (center<=end){
            arr[low++]=nums[center++];
        }

        for(int i=start;i<=end;i++){
            nums[i]=arr[i];
        }
    }


堆排序
对简单选择排序的优化。

将序列构建成大顶堆。
将根节点与最后一个节点交换,然后断开最后一个节点。
重复第一、二步,直到所有节点断开。
  //堆排序
    private boolean isLeaf(int nums[],int pos)
    {
        //没有叶子节点
        return pos*2+1>=nums.length;
    }

    private void swap(int[] nums,int pos1,int pos2)
    {
        int tmp;
        tmp=nums[pos2];
        nums[pos2]=nums[pos1];
        nums[pos1]=tmp;
    }

    private void shiftdown(int[] nums,int pos)
    {
        while(!isLeaf(nums,pos))
        {
            int left=pos*2+1;
            int right=pos*2+2;
            if(right<nums.length)
            {
                left=nums[left]>nums[right]?left:right;
            }
            //是否需要调整堆
            if(nums[pos]>=nums[left]) return;
            swap(nums,pos,left);
            pos=left;
        }
    }
    public void buildHeap(int nums[])
    {
        for(int i=nums.length/2-1;i>=0;i--)
        {
            shiftdown(nums,i);
        }
    }

    public void heapSort(int nums[])
    {
        for(int i=nums.length-1;i>=0;i--)
        {
            swap(nums,0,i);
            shiftdown(nums,i);
        }
    }


总结
一、稳定性:
稳定:冒泡排序、插入排序、归并排序和基数排序
不稳定:选择排序、快速排序、希尔排序、堆排序
二、平均时间复杂度
O(n^2):直接插入排序,简单选择排序,冒泡排序。

在数据规模较小时(9W内),直接插入排序,简单选择排序差不多。当数据较大时,冒泡排序算法的时间代价最高。性能为O(n^2)的算法基本上是相邻元素进行比较,基本上都是稳定的。

O(nlogn):快速排序,归并排序,希尔排序,堆排序。

其中,快排是最好的,其次是归并和希尔,堆排序在数据量很大时效果明显。

三、排序算法的选择
数据规模较小
(1)待排序列基本序的情况下,可以选择直接插入排序;

(2)对稳定性不作要求宜用简单选择排序,对稳定性有要求宜用插入或冒泡

数据规模不是很大
(1)完全可以用内存空间,序列杂乱无序,对稳定性没有要求,快速排序,此时要付出log(N)的额外空间。

(2)序列本身可能有序,对稳定性有要求,空间允许下,宜用归并排序

数据规模很大
(1)对稳定性有求,则可考虑归并排序。

(2)对稳定性没要求,宜用堆排序

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

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

相关文章

centos7部署websocket

django项目&#xff0c;中间使用websocket进行通讯&#xff0c;想部署到服务器上&#xff0c;按照之前部署项目的思路进行部署&#xff0c;但是失败了。解决了一下&#xff0c;在此记录。 主项目下有一子app&#xff0c;一模版文件&#xff0c;一静态文件。项目中主要用到dweb…

Factorization Machines(论文笔记)

样例一&#xff1a; 一个简单的例子,train是一个字典&#xff0c;先将train进行“one-hot” coding&#xff0c;然后输入相关特征向量&#xff0c;可以预测相关性。 from pyfm import pylibfm from sklearn.feature_extraction import DictVectorizer import numpy as np tra…

【MATLAB第59期】基于MATLAB的混沌退火粒子群CSAPSO-BP、SAPSO-BP、PSO-BP优化BP神经网络非线性函数拟合预测/回归预测对比

【MATLAB第59期】基于MATLAB的混沌退火粒子群CSAPSO-BP、SAPSO-BP、PSO-BP优化BP神经网络非线性函数拟合预测/回归预测对比 注意事项 不同版本matlab 不同电脑 加上数据集随机&#xff0c;BP权值阈值随机&#xff0c;进化算法种群随机&#xff0c;所以运行结果不一定和我运行…

集成了32位Cortex®M0内核XMC1302T038X0200AB、XMC1302Q040X0200AB 32MHz 200KB 闪存 工业MCU

XMC1000 32位工业 MCU 将 ARM Cortex™-M0 核心与领先的 65nm 制造工艺相结合&#xff0c;克服了目前 8 位设计的局限。XMC1000系列让目前的 8 位用户有机会享受 32 位的功耗&#xff0c;同时不在价格或易用性上做出妥协。XMC1000 在其细分市场提供最为广泛的闪存产品线&#x…

3分钟,快速上手Postman接口测试

Postman是一个用于调试HTTP请求的工具&#xff0c;它提供了友好的界面帮助分析、构造HTTP请求&#xff0c;并分析响应数据。实际工作中&#xff0c;开发和测试基本上都有使用Postman来进行接口调试工作。有一些其他流程的工具&#xff0c;也是模仿的Postman的风格进行接口测试工…

下载|GitLab 2023 年 DevSecOps 全球调研报告:安全左移深入人心、AI/ML 蔚然成风

目录 谁应该对应用程序安全负主要责任&#xff1f; 安全实践的最大挑战 AI 驱动研发&#xff0c;提升研发效率 各个角色使用的工具数量是多少&#xff1f; 一体化 DevSecOps 平台有哪些优势&#xff1f; 56%、74%、71%、65%、57% 这些数字和 DevSecOps 结合在一起&#xf…

android adb命令获取处于当前屏幕的Activity

android adb命令获取处于当前屏幕的Activity 使用adb命令&#xff1a; adb shell dumpsys activity activities 输出&#xff0c;例如: ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities) Display #0 (activities from top to bottom): * Task{38ef601 #5281 typ…

Java当中的栈

栈的理解 栈&#xff08;Stack&#xff09;是一种受限的线性数据结构&#xff0c;所谓受限是指栈只暴露栈顶和栈底的操作&#xff0c;其底层是由数组实现的。栈的特性是先进后出。 常用方法 注意上面的peek()方法和pop()方法的区别&#xff01; 实例 import java.util.Stack…

grpc中间件之链路追踪(otel+jaeger)

参考文档 https://github.com/grpc-ecosystem/go-grpc-middleware/blob/main/examples/client/main.go https://github.com/grpc-ecosystem/go-grpc-middleware/blob/main/examples/server/main.go https://github.com/open-telemetry/opentelemetry-go/blob/main/example/jaeg…

【Rust 基础篇】Rust 通道实现单个消费者多个生产者模式

导言 在 Rust 中&#xff0c;我们可以使用通道&#xff08;Channel&#xff09;来实现单个消费者多个生产者模式&#xff0c;简称为 MPMC。MPMC 是一种常见的并发模式&#xff0c;适用于多个线程同时向一个通道发送数据&#xff0c;而另一个线程从通道中消费数据的场景。本篇博…

搭建elasticsearch过程中遇到问题记录

##1.新建用户 解压es之前&#xff0c;新建用户做后续操作&#xff0c;root用户无法启动es。 ##2.增大普通用户可打开最大文件数 ##3.增大普通用户可启动线程数 ##4.增大用户可使用虚拟内存 编辑 /etc/sysctl.conf&#xff0c;追加以下内容&#xff1a; vm.max_map_count262144…

sql中group by 的使用

1、概述 Group By 从字面意义上理解就是根据By指定的规则对数据进行分组&#xff0c;所谓的分组就是将一个数据集划分为若干个小区域&#xff0c;然后针对若干个小区域进行数据处理 2、原始表 3、简单的Group By 示例1 select 类别&#xff0c;数量 as 数量之和 from A gro…

android studio 离线打包配置push模块

1.依赖引入 SDK\libs aps-release.aar, aps-unipush-release.aar, gtc.aar, gtsdk-3.2.11.0.aar, 从android studio的sdk中找到对应的包放到HBuilder-Integrate-AS\simpleDemo\libs下面 2.打开build.gradle&#xff0c;在defaultConfig添加manifestPlaceholders节点&#xff0c…

【代码随想录 | Leetcode | 第十天】哈希表 | 三数之和 | 四数之和

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来哈希法~三数之和 | 四数之和的分享✨ 目录 前言15. 三数之和18. 四数之和总结 15. 三数之和 ✨题目链接点这里 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], num…

JVM运行时区域——对象创建内存分配过程

新创建的对象&#xff0c;都存放在伊甸园区域&#xff0c;当垃圾回收时&#xff0c;将伊甸园区域的垃圾数据销毁&#xff0c;然后将存活的对象转移到幸存者0区域&#xff0c;之后创建的新的对象还是存放在伊甸园区域&#xff0c;等到再次垃圾回收后&#xff0c;将伊甸园区域和幸…

RabbitMQ帮助类的封装

RabbitMQ帮助类的封装 基本部分 public class RabbitMQInvoker {#region Identy private static IConnection _CurrentConnection null;private readonly string _HostName null;private readonly string _UserName null;private readonly string _Password null;#endreg…

开篇词 | 「安卓学习路线」

操作系统 Java 集合、反射、泛型、并发编程&#xff08;线程安全&#xff0c;锁机制、线程隔离&#xff09;&#xff0c;IO 流&#xff0c;JVM&#xff08;内存结构、垃圾回收&#xff09; 安卓&#xff08;通过实践项目来学习基础知识&#xff09; 基础知识 Activity 和 Ser…

HTML5——基础知识及使用

HTML 文件基本结构 <html><head><title>第一个页面</title></head><body>hello world</body> </html> html 标签是整个 html 文件的根标签(最顶层标签).head 标签中写页面的属性.body 标签中写的是页面上显示的内容.title 标…

Ansible自动化运维学习——综合练习

目录 (一)练习一 1.新建一个role——app 2.创建文件 3.删除之前安装的httpd服务和apache用户 4.准备tasks任务 (1)创建组group.yml (2)创建用户user.yml (3)安装程序yum.yml (4)修改模板httpd.conf.j2 (5)编写templ.yml (6)编写start.yml (7)编写copyfile.yml (8…

Python爬虫技术及其原理详解

概要 随着互联网的发展&#xff0c;大量的数据被存储在网络上&#xff0c;而我们需要从中获取有用的信息。Python作为一种功能强大且易于学习的编程语言&#xff0c;被广泛用于网络爬虫的开发。本文将详细介绍Python爬虫所需的技术及其原理&#xff0c;并提供相关的代码案例。 …