数据结构排序算详解(动态图+代码描述)

目录

1、直接插入排序(升序)

2、希尔排序(升序) 

3、选择排序(升序)

方式一(一个指针)

方式二(两个指针)

4、堆排序(升序)

 5、冒泡排序(升序)

6、快速排序 (升序)

方式一(Hoare方法)

方式二(挖坑法) 

 快排改进算法(三数取中)

7、归并排序

8、总结


1、直接插入排序(升序)

描述对于一个数组i从第二个数据开始比较,j=i-1,j<0停止,每次i下标元素放到临时变量tmp中与j下标比较,如果大于j下标,tmp还放回原位置,i和j都加加,如果小于j下标,j--,直到找到大于j下标元素,tmp放到j+1下标

时间复杂度:最好情况下O(n),最坏情况O(n^2)

空间复杂度:O(1)

//直接插入排序
//时间复杂度:最好情况下O(n),最坏情况O(n^2)
public class Test1 {
    public static void sort(int []array){
        for (int i = 1; i <array.length ; i++) {
            int tmp=array[i];
            int j = i-1;
            for (; j >=0 ; j--) {
                if(tmp<array[j])
                    array[j+1]=array[j];
                else break;
            }
            array[j+1]=tmp;
        }
    }
}

2、希尔排序(升序) 

描述:我们先对数组中数据分组,数组长度即位N,具体先分为gap组,gap=N/2,N/4,N/8.....1。然后对每一组直接插入排序。

时间复杂度:O(n*log2(N)),空间复杂度:O(1)

每种颜色一组例如:

例如:

public static void ShellSort(int [] array){
        int gap=array.length;//10
        while (gap>1){
            gap=gap/2;
            Sort(array,gap);//5,2,1
        }
    }
    private static void Sort(int [] array,int gap){
        for (int i = gap; i <array.length ; i++) {
            int tmp=array[i];
            int j = i-gap;
             //每组直接插入排序
            for (; j >=0 ; j=j-gap) {
                if (tmp<array[j])array[j+gap]=array[j];
                else break;
            }
            array[j+gap]=tmp;
        }

3、选择排序(升序)

方式一(一个指针)


描述: 每次找最小值下标,与i下标交换,i++

空间复杂度O(1),时间复杂度:O(N^2)

 public static void selcetSort(int [] array){
        for (int i = 0; i <array.length ; i++) {
            int min=i;//记录每次最小值下标
            for (int j = i+1; j <array.length ; j++)
                if (array[j]<array[min])min=j;
            swap(min,i,array);
        }
    }
 private static void swap(int i ,int j,int [] array){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

方式二(两个指针)

思路left,right指向数组的两端,每次遍历找到最大值和最小值,分别赋值给lefgt和right

 public static void selectSort2(int[] array) {
        int left = 0;
        int right = array.length-1;
        int i;
        while (left < right) {
        //i  minIndex   maxIndex
            int minIndex=left,maxIndex=right;
            i=left+1;
            for(;i<right;i++){
                if (array[i]<=array[minIndex])minIndex=i;
                if (array[i]>array[maxIndex])maxIndex=i;
            }
            swap(left,minIndex,array);
            swap(right,maxIndex,array);
            left++;
            right--;
        }
    }
    private static void swap(int i ,int j,int [] array){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

4、堆排序(升序)

思路:先创建成大根堆,每次排序把根节点与最后位置元素交换后向下调整,下一次根节点与end-1下标交换后向下调整,直到end<0;结束

 public static void HeapSort(int[]array){
        creatHeap(array.length,array);//创建大根堆
        int end=array.length-1;
        while (end>0){
            swap(end,0,array);
            signHeap(0,end,array);//向下调整不挑最后一个所以后减减
            end--;
        }

    }
    public static void creatHeap(int end,int [] array){
        int preheap;//每次的根节点
        for ( preheap=(end-1-1)/2;preheap>=0;preheap--){
            signHeap(preheap,end, array);
        }

    }
    //向下调整为大根堆为例
    private static void signHeap(int preheap,int end,int [] array){//向下调整
        int child=preheap*2+1;//preheap左子树下标
        while (child<end){
            if(child+1<end&&array[child]<array[child+1])child++;
            //现在child指向孩子节点的最大值
            if (array[preheap]<array[child]){
                swap(preheap,child,array);
                preheap=child;
                child=child*2+1;
            }
            else break;
        }
    }
    private static void swap(int i ,int j,int [] array){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

 5、冒泡排序(升序)

 

时间复杂度:O(N^2),空间复杂度O(1)
 public static void bubbleSort(int [] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flag=false;
            for (int j = 0; j < array.length-1; j++) {
                if (array[j]>array[j+1]){
                    swap(j,j+1,array);
                    flag=true;
                }
            }
            if (flag==false)break;
        }
    }
    private static void swap(int i ,int j,int [] array){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

6、快速排序 (升序)

方式一(Hoare方法

描述: 

每次都是最左边的元素是基点,从左边往右找到比基点大的跟从右往左找到比基点小的交换,最后left和right交点和基点交换,这样排完一次后交点左边比交点值小,后边大,分左右递归在排

时间复杂度:O(Nlog2(N)),空间复杂度O(log2(N))
    public static void quick(int [] array){
        int start=0,end=array.length-1;
        quickSort(array,start,end);
    }
    private static void quickSort(int [] array,int start,int end){
        if(start>=end)return;
        int mid=sort(array,start,end);
        quickSort(array,start,mid-1);
        quickSort(array,mid+1,end);
    }
    private static int sort(int [] array,int left,int right){
        int tmp=array[left];//基准
        int i=left;
        //先写右的right--,否则一遍走到left==right后与i下标交换的那一次且仅仅一次将会不有序
        while (left<right) {
            while (left < right && tmp <=array[right]) right--;//找到比tmp小的数
            while (left < right && tmp >= array[left]) left++;//找到比tmp大的数
            swap(right, left, array);
        }
        swap(left,i,array);
        return left;//left==right==mid
    }
    private static void swap(int i ,int j,int [] array){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

方式二(挖坑法) 

 思想:每次都是最左边的元素是基点,保存基点下标,此处就是一个坑,从右往左找到比基点小的放到基点下标,放到坑处 ,刚从右边放过来的元素位置就有是一个新的坑,我们再从左往右找到比基点大的元素放到新坑,当然这里又是一个坑。。。

时间复杂度:O(Nlog2(N)),空间复杂度O(log2(N))

    public static void quick(int [] array){
        int start=0,end=array.length-1;
        quickSort(array,start,end);
    }
    private static void quickSort(int [] array,int start,int end){
        if(start>=end)return;
        int mid=sort(array,start,end);
        quickSort(array,start,mid-1);
        quickSort(array,mid+1,end);
    }
    private static int sort(int [] array,int left,int right){
        int tmp=array[left];//基准
        int i=left;
        //先写右的right--,否则一遍走到left==right后与i下标交换后的那一次将会不有序
        while (left<right) {
            while (left < right && tmp <=array[right]) right--;//找到比tmp小的数
            array[left]=array[right];
            while (left < right && tmp >= array[left]) left++;//找到比tmp大的数
            array[right]=array[left];
        }
        array[left]=tmp;//最后入坑
        return left;//left==right==mid
    }

 快排改进算法(三数取中)

思想:三数取中法,index是每次左右短点和中间点第二大的数字,防止分组不太对称,成为串,这样时间复杂度变高
public static void quick(int [] array){
        int start=0,end=array.length-1;
        quickSort(array,start,end);
    }
    private static void quickSort(int [] array,int start,int end){
        if(start>=end)return;
        //三数取中法,index是每次左右短点和中间点第二大的数字
        //防止分组不太对称,成为串,这样时间复杂度变高
        int index=indexleNum(array,start,end);
        //快排排序开始
        int mid=sort(array,start,end);
        quickSort(array,start,mid-1);
        quickSort(array,mid+1,end);
    }
    //挖坑法
    private static int sort(int [] array,int left,int right){
        int tmp=array[left];//基准
        int i=left;
        //先写右的right--,否则一遍走到left==right后与i下标交换的那一次且仅仅一次将会不有序
        while (left<right) {
            while (left < right && tmp <=array[right]) right--;//找到比tmp小的数
            array[left]=array[right];
            while (left < right && tmp >= array[left]) left++;//找到比tmp大的数
            array[right]=array[left];
        }
        array[left]=tmp;//最后入坑
        return left;//left==right==mid
    }
    private static int indexleNum(int [] array,int left,int right){
        int index=left+((left+right)/2);
        //也就三个数据,空间复杂度不高,所以可以建立一个新的数组,用冒泡
        int [] b=new int[3];
        for (int i = 0; i < b.length-1; i++) {
            boolean flag=false;
            for (int j = 0; j < array.length-1; j++) {
                if (array[j]>array[j+1]){
                    swap(j,j+1,array);
                    flag=true;
                }
            }
            if (flag==false)break;
        }
        return b[1];
    }
    private static void swap(int i ,int j,int [] array){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

7、归并排序

时间复杂度:O(Nlog2(N)),空间复杂度O(N)

 

 public static void mergerSort(int [] array){
        mergeFunc(array,0,array.length-1);
    }
    private static void mergeFunc(int [] array,int left,int right){
        if(left>=right){
            return;
        }
        int mid=left+((right-left)>>1);
        mergeFunc(array,left,mid);
        mergeFunc(array,mid+1,right);
        //左右拆分完毕,开始合并
        merge(array,mid,left,right);
    }
    private static void merge(int []array,int mid,int left,int right){
        int start1=left;
        int end1=mid;
        int start2=mid+1;
        int end2=right;
        int [] tmp=new int[right-left+1];
        int k=0;
        //保证两个表都有数据
        while (start1<=end1&&start2<=end2){
            if (array[start1]<=array[start2])tmp[k++]=array[start1++];
            else {
                tmp[k++]=array[start2++];
            }
        }
        //如果s2没有数据了但是s1中还有数据
        while (start1<=end1)tmp[k++]=array[start1++];
        //如果s1没有数据了但是s2中还有数据
        while (start2<=end2)tmp[k++]=array[start2++];
        //放回到原来数组
        for (int i = 0; i < k; i++) {
            array[i+left]=tmp[i];//i+left防止覆盖数据
        }
    }

8、总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IP报文格式

IP报文格式 报文格式 图1 IP头格式 表1 IP头字段解释 字段长度含义Version4比特 4&#xff1a;表示为IPV4&#xff1b;6&#xff1a;表示为IPV6。IHL4比特首部长度&#xff0c;如果不带Option字段&#xff0c;则为20&#xff0c;最长为60&#xff0c;该值限制了记录路由选项。…

Flink问题解决及性能调优-【Flink根据不同场景状态后端使用调优】

Flink 实时groupby聚合场景操作时&#xff0c;由于使用的是rocksdb状态后端&#xff0c;发现CPU的高负载卡在rocksdb的读写上&#xff0c;导致上游算子背压特别大。通过调优使用hashmap状态后端代替rocksdb状态后端&#xff0c;使吞吐量有了质的飞跃&#xff08;20倍的性能提升…

【Tomcat与网络1】史前时代—没有Spring该如何写Web服务

在前面我们介绍了网络与Java相关的问题&#xff0c; 最近在调研的时候发现这块内容其实非常复杂&#xff0c;设计的内容多而且零碎&#xff0c;想短时间梳理出整个体系是不太可能的&#xff0c;所以我们还是继续看Tomcat的问题&#xff0c;后面有网络的内容继续补充吧。 目录 …

简单记录一下如何安装python以及pycharm(图文教程)(可供福建专升本理工类同学使用)

本教程主要给不懂计算机的或者刚刚开始学习python的同学&#xff08;福建专升本理工类&#xff09;&网友学习使用&#xff0c;基础操作&#xff0c;比较详细&#xff0c;其他问题等待补充&#xff01; 安装Python 1.进入python官网&#xff08;https://www.python.org/&a…

泽众云真机-远程真机测试常见问题汇总及解决办法

泽众云真机通过网页操作接入云端的真实手机&#xff0c;覆盖市场海量机型&#xff0c;远程操控快速流畅&#xff0c;用户随时随地进行测试&#xff0c;调试应用&#xff0c;快速定位问题&#xff0c;被测应用轻松获得FPS、CPU、Memory、CTemp、Network、FrameTime等性能参数&am…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-1事件处理

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>事件处理</title> </head><body> <input id"btn" type"button" name"btn" value"提交" /> <…

计算机网络-奈氏准则和香农定理(码间串扰 二者区别)

文章目录 失真失真的一种现象-码间串扰奈氏准则&#xff08;奈溃斯特定理&#xff09;例题 香农定理例题 奈氏和香农 失真 就是指与原来的不一样了 两种情况 前三个是正相关&#xff0c;最后一个是负相关 码元传输速率越快&#xff0c;失真程度越严重的原因可能包括以下几点…

Vue3中的ref和shallowRef、reactive和shallowReactive

一&#xff1a;ref、reactive简介 ref和reactive是Vue3中定义响应式数据的一种方式。ref通常用来定义基础类型数据。reactive通常用来定义复杂类型数据。 二、shallowRef、shallowReactive简介 shallowRef和shallowReactive是Vue3中定义浅层次响应式数据的方式 三、Api使用对比…

项目中日历管理学习使用

一些项目中会有日历或日期设置&#xff0c;最基本的会显示工作日&#xff0c;休息日&#xff0c;节假日等等&#xff0c;下面就是基于项目中的日历管理功能&#xff0c;要显示工作日&#xff0c;休息日&#xff0c;节假日 效果图 获取国家法定节假日工具类 public class Holi…

20240126请问在ubuntu20.04.6下让GTX1080显卡让whisper工作在large模式下?

20240126请问在ubuntu20.04.6下让GTX1080显卡让whisper工作在large模式下&#xff1f; 2024/1/26 21:19 问GTX1080模式使用large该如何配置呢&#xff1f; 这个问题没有完成&#xff0c;可能需要使用使用显存更大的显卡了&#xff01; 比如GTX1080Ti 11GB&#xff0c;更猛的可…

05-TiDB 之 HTAP 快速上手

混合型在线事务与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) 功能 HTAP 存储引擎&#xff1a;行存 与列存 同时存在&#xff0c;自动同步&#xff0c;保持强一致性。行存 OLTP &#xff0c;列存 OLAPHTAP 数据一致性&#xff1a;作为一个分布式事务…

mac/macos上编译electron源码

官方教程&#xff1a;Build Instructions | Electron 准备工作这里不写了&#xff0c;参考官方文档&#xff0c;还有上一篇windows编译electron electron源码下载及编译-CSDN博客 差不多步骤&#xff0c;直接来 网络记得使用魔法 下载编译步骤 0. 选择目录很重要&#xff0…

02 Redis之配置文件

3. Redis配置文件 3.1 网络部分 首先明确&#xff0c;tcp-backlogestablished Linux 内核 2.2 版本之后&#xff08;现在大部分都是3.x了&#xff09; TCP 系统中维护了两个队列, 用来存放TCP连接 a. SYN_RECEIVED 队列中存放未完成三次握手的连接 b. ESTABLISHED队列中存放已…

算力、应用、方案,联想布局全栈AI,以自身制造与供应链范本助力千行百业智能化转型升级

1月23日-24日&#xff0c;联想集团举办主题为“算领AI时代 筑基智能变革”的擎智媒体沙龙和新IT思享会“走进联想”活动。在活动中&#xff0c;联想集团副总裁、中国区首席市场官王传东表示&#xff0c;今年是联想成立40周年&#xff0c;联想已构建了全栈智能布局&#xff0c;将…

派网AX50C做多宽带路由和核心交换机配置实战教程

接近300办公人员的工厂需要网络升级&#xff0c;我规划设计和部署实施了以下方案&#xff0c;同样是简约不简单&#xff0c;在满足性能需求稳定性的前提下&#xff0c;既有经济性&#xff0c;又有安全性。 派网做路由器&#xff0c;刚好开启默认防病毒策略&#xff0c;省下来一…

携程开源 基于真实请求与数据的流量回放测试平台、自动化接口测试平台AREX

携程开源 基于真实请求与数据的流量回放测试平台、自动化接口测试平台AREX 官网文档 基于真实请求与数据的流量回放测试平台、自动化接口测试平台AREX 这篇文章稍稍水一下&#xff0c;主要讲下部署过程里踩的坑&#xff0c;因为部署的过程主要是运维同学去处理了&#xff0c;我…

力扣每日一题 ---- 1039. 多边形三角剖分的最低得分

这题的难点在哪部分呢&#xff0c;其实是怎么思考。这道题如果之前没做过类似的话&#xff0c;还是很难看出一些性质的&#xff0c;这题原本的话是没有图片把用例显示的这么详细的。这题中有个很隐晦的点没有说出来 剖出来的三角形是否有交叉&#xff0c;这题中如果加一个三角…

【HarmonyOS应用开发】TypeScript快速入门(二)

内容比较长&#xff0c;干货满满&#xff0c;全是实战操作内容&#xff0c;希望耐心观看&#xff0c;如果对你有所帮助&#xff0c;请点个赞&#xff01; ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript&#xff08;简称TS&#xff09;的基础上&#xff0c;匹配ArkUI…

力扣hot100 课程表 拓扑序列

Problem: 207. 课程表 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 三叶题解 复杂度 时间复杂度: O ( n m ) O(nm) O(nm) 空间复杂度: O ( n m ) O(nm) O(nm) Code class Solution{int N 100010, M 5010, idx;int[] in new int[N];// in[i] 表示节…

第六篇【传奇开心果系列】Python的OpenCV库技术点案例示例:摄像头标定

传奇开心果博文系列 系列博文目录Python的OpenCV库技术点案例示例系列 博文目录一、前言二、OpenCV摄像头标定介绍三、摄像头内外参数标定示例代码和扩展四、立体视觉标定示例代码和扩展五、归纳总结 系列博文目录 Python的OpenCV库技术点案例示例系列 博文目录 一、前言 O…
最新文章