十大基础算法

一、选择排序

过程简单描述:
首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法我们称之为选择排序

为方便理解我还准备了动图:

.

public class SelectionSort {

    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 8, 1, 7, 9, 4, 2};
        //定义内外两层循环,从最外层循环第一个值开始匹配,内层循环从外层循环加以开始向后匹配
        //如果遇到小的值就进行交换
        //外层循环到倒数第二为止,内层循环到倒数第一为止
        for (int i = 0; i < arr.length-1; i++) {
            int min = i;
            for (int j = i+1; j < arr.length; j++) {
                if(arr[i]>=arr[j]){
                    min = j;
                    int temp = arr[i];
                    arr[i] = arr[min];
                    arr[j] = temp;
                }
            }
        }
        CommonUtils.print(arr);
    }
}

性质:1、时间复杂度:O(n2)  2、空间复杂度:O(1)  3、非稳定排序  4、原地排序

二、插入排序

我们在玩打牌的时候,你是怎么整理那些牌的呢?一种简单的方法就是一张一张的来,将每一张牌插入到其他已经有序的牌中的适当位置。当我们给无序数组做排序的时候,为了要插入元素,我们需要腾出空间,将其余所有元素在插入之前都向右移动一位,这种算法我们称之为插入排序

过程简单描述:

1、从数组第2个元素开始抽取元素。

2、把它与左边第一个元素比较,如果左边第一个元素比它大,则继续与左边第二个元素比较下去,直到遇到不比它大的元素,然后插到这个元素的右边。

3、继续选取第3,4,….n个元素,重复步骤 2 ,选择适当的位置插入。

为方便理解我还准备了动图:

public class InsertionSort {
    public static void main(String[] args) {
        int[] a = { 9, 3, 1, 4, 6, 8, 7, 5, 2 };
        for (int i = 1; i < a.length; i++) {
            //内层比较是从外层的赋值为起始点
            //该值会和它前面的值比较,如果比前面的值小就交换
            for (int j = i;j>0; j--) {
                if(a[j]<a[j-1]){
                    CommonUtils.swap(a,j,j-1);
                }
            }
        }
        CommonUtils.print(a);
    }
}

三、冒泡排序

1、把第一个元素与第二个元素比较,如果第一个比第二个大,则交换他们的位置。接着继续比较第二个与第三个元素,如果第二个比第三个大,则交换他们的位置….

我们对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样一趟比较交换下来之后,排在最右的元素就会是最大的数。

除去最右的元素,我们对剩余的元素做同样的工作,如此重复下去,直到排序完成。

为方便理解我还准备了动图:

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 8, 1, 7, 9, 4, 2};
        for (int i = 0; i < arr.length; i++) {
            //内层循环像指针一样指导着程序运行
            for (int j = 0; j < arr.length-i-1; j++) {

                if(arr[j]>arr[j+1]){
                    CommonUtils.swap(arr,j,j+1);
                }
            }
        }

        CommonUtils.print(arr);
    }
}

四、冒泡排序

希尔排序可以说是插入排序的一种变种。无论是插入排序还是冒泡排序,如果数组的最大值刚好是在第一位,要将它挪到正确的位置就需要 n - 1 次移动。也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相邻元素交换很多次才能到达正确的位置,这样是相对比较花时间了。

希尔排序就是为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。

希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。

为方便理解我还准备了图片:

public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 8, 1, 7, 9, 4, 2};
        int h = arr.length/2;
        for (int gap = h; gap > 0; gap--) {//间隔的循环
            for (int j = 0; j < arr.length-gap; j++) {
                if(arr[j]>arr[j+gap]){
                    CommonUtils.swap(arr,j,j+gap);
                }
            }

        }

        CommonUtils.print(arr);
    }
}

五、归并排序

将一个大的无序数组有序,我们可以把大的数组分成两个,然后对这两个数组分别进行排序,之后在把这两个数组合并成一个有序的数组。由于两个小的数组都是有序的,所以在合并的时候是很快的。

通过递归的方式将大的数组一直分割,直到数组的大小为 1,此时只有一个元素,那么该数组就是有序的了,之后再把两个数组大小为1的合并成一个大小为2的,再把两个大小为2的合并成4的 ….. 直到全部小的数组合并起来。

为方便理解我还准备了动图:

public class MergeSort {

    public static void main(String[] args) {
        int[] arr = {1,4,7,8,3,6,9};
        sort(arr, 0, arr.length-1);

        CommonUtils.print(arr);
    }
    static void sort(int[] arr, int left, int right) {
        if(left==right){
            return;
        }
        int mid = left + (right-left)/2;
        sort(arr,left,mid);
        sort(arr,mid+1,right);
        merge(arr,left,mid+1,right);
    }


    //先定义合并的方法
    static void merge(int[] arr, int leftPtr, int rightPtr, int rightBound) {
        int i = leftPtr;
        int j = rightPtr;
        int mid = rightPtr -1;
        int[] temp = new int[rightBound - leftPtr + 1];
        int tempPtr = 0;

        //进行比较赋值
        while (i<=mid&&j<=rightBound){
            if(arr[i]>arr[j]){
                temp[tempPtr]=arr[j];
                j++;
                tempPtr++;
            }else {
                temp[tempPtr]=arr[i];
                i++;
                tempPtr++;
            }
        }

        //将未放入临时数组的数放入临时数组
        while(i<=mid) temp[tempPtr++] = arr[i++];
        while(j<=rightBound) temp[tempPtr++] = arr[j++];

        //数组复制
        for (int i1 = 0; i1 < temp.length; i1++) {
            arr[leftPtr+i1]=temp[i1];
        }
    }
}

六、快速排序

我们从数组中选择一个元素,我们把这个元素称之为中轴元素吧,然后把数组中所有小于中轴元素的元素放在其左边,所有大于或等于中轴元素的元素放在其右边,显然,此时中轴元素所处的位置的是有序的。也就是说,我们无需再移动中轴元素的位置。

从中轴元素那里开始把大的数组切割成两个小的数组(两个数组都不包含中轴元素),接着我们通过递归的方式,让中轴元素左边的数组和右边的数组也重复同样的操作,直到数组的大小为1,此时每个元素都处于有序的位置

为方便理解我还准备了动图:

public class QuickSort {

    public static void main(String[] args) {
        int[] arr = {1,5,7,6,4};
        sort(arr,0,arr.length-1);

        CommonUtils.print(arr);
    }

    static void sort(int[] arr, int leftBound, int rightBound) {
        if(leftBound>=rightBound) {
            return;
        }
        int mid = partition(arr, leftBound, rightBound);
        sort(arr,leftBound,mid-1);
        sort(arr,mid+1,rightBound);
    }

    static int partition(int[] arr, int leftBound, int rightBound) {
        int left = leftBound;
        int mid = rightBound;
        int right = rightBound-1;

        while (left<=right){
            //1、这两个指针分别寻找小于标杆和大于标杆的数,找到以后指针停止
            //2、交换两边指针停止位置的数
            //3、将标杆放到中间的位置
            while (left<=right&&arr[left]<=arr[mid]){
                left++;
            }
            while (left<=right&&arr[right]>arr[mid]){
                right--;
            }
            if(left<right){
                CommonUtils.swap(arr,left,right);
            }
        }
        //把标杆放中间
        CommonUtils.swap(arr,left,rightBound);
        return left;
    }
}

七、计数排序

计数排序是一种适合于最大值和最小值的差值不是不是很大的排序。

基本思想:就是把数组元素作为数组的下标,然后用一个临时数组统计该元素出现的次数,例如 temp[i] = m, 表示元素 i 一共出现了 m 次。最后再把临时数组统计的数据从小到大汇总起来,此时汇总起来是数据是有序的。

为方便理解我还准备了动图:

public class CountSort {
    public static void main(String[] args) {

        int[] arr = {2, 4, 2, 3, 7, 1, 1, 0, 0, 5, 6, 9, 8, 5, 7, 4, 0, 9};

        int[] result = sort(arr);

        CommonUtils.print(result);

    }
    public static int[] sort(int[] arr) {
        int[] temp = new int[10];
        for (int a : arr) {
            temp[a]++;
        }

        int[] result = new int[arr.length];
        int r = 0;
        for (int i = 0; i < temp.length; i++) {

            while (temp[i]>0){
                result[r]=i;
                r++;
                temp[i]--;
            }
        }
        return result;
    }
}

八、桶排序

桶排序就是把最大值和最小值之间的数进行瓜分,例如分成  10 个区间,10个区间对应10个桶,我们把各元素放到对应区间的桶中去,再对每个桶中的数进行排序,可以采用归并排序,也可以采用快速排序之类的。

之后每个桶里面的数据就是有序的了,我们在进行合并汇总。

为方便理解我还准备了图片:

public class BucketSort {

    public static void main(String[] args) {

        int[] arr = {2, 4, 2, 3, 7,0};

        int[] result = sort(arr);

        CommonUtils.print(result);

    }

    public static int[] sort(int[] arr) {
        int max = findMax(arr);
        int mini = findMini(arr);
        int group = (max-mini)/5+1;
        List<List<Integer>> totalBucket = new LinkedList<>();

        //初始化桶
        for (int i = 0; i < group; i++) {
            totalBucket.add(new LinkedList<Integer>());
        }

        for (int i = 0; i < arr.length; i++) {
            //得到所在区间
            int i1 = (arr[i] - mini) / (max - mini);
            //向所在区间添加元素
            totalBucket.get(i1).add(arr[i]);
        }

        //复制结果
        for (List<Integer> integers : totalBucket) {
            Collections.sort(integers);
        }




        //复制结果
        int[] result = new int[arr.length];
        int r = 0;
        for (int i = 0; i < totalBucket.size(); i++) {
            for (int i1 = 0; i1 < totalBucket.get(i).size(); i1++) {
                result[r]= totalBucket.get(i).get(i1);
                r++;
            }
        }
        return result;
    }

    public static int findMax(int[] arr) {
        int max = arr[0];
        for (int i : arr) {
            if(i>max){
                max = i;
            }
        }
        return max;
    }

    public static int findMini(int[] arr) {
        int mini = arr[0];
        for (int i : arr) {
            if(i<mini){
                mini = i;
            }
        }
        return mini;
    }
}

九、基数排序

基数排序的排序思路是这样的:先以个位数的大小来对数据进行排序,接着以十位数的大小来多数进行排序,接着以百位数的大小……

排到最后,就是一组有序的元素了。不过,他在以某位数进行排序的时候,是用“桶”来排序的。

由于某位数(个位/十位….,不是一整个数)的大小范围为0-9,所以我们需要10个桶,然后把具有相同数值的数放进同一个桶里,之后再把桶里的数按照0号桶到9号桶的顺序取出来,这样一趟下来,按照某位数的排序就完成了

为方便理解我还准备了动图:

public class RadioSort {
    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 8, 100, 7, 9, 4, 20};
        sort(arr);
        CommonUtils.print(arr);
    }

    public static int[] sort(int[] arr) {
       if(arr==null||arr.length==2) {
           return arr;
       }
       int max = findMax(arr);
       int num = 1;
       while (max/10>0){
           max= max/10;
           num++;
       }

        List<List<Integer>> totalBucket = new LinkedList<>();

        //初始化桶
        for (int i = 0; i < 10; i++) {
            totalBucket.add(new LinkedList<Integer>());
        }
        for (int i = 0; i < num; i++) {
            //放入对应的桶
            for (int j = 0; j < arr.length; j++) {
                int location = (arr[j] / (int)Math.pow(10,i)) % 10;
                totalBucket.get(location).add(arr[j]);
            }


            int k = 0;
            for (List<Integer> integers : totalBucket) {
                for (Integer integer : integers) {
                    arr[k++]=integer;
                }
                integers.clear();
            }


        }



        return arr;
    }


    public static int findMax(int[] arr) {
        int max = arr[0];
        for (int i : arr) {
            if(i>max){
                max = i;
            }
        }
        return max;
    }
}

十、堆排序

堆的特点就是堆顶的元素是一个最值,大顶堆的堆顶是最大值,小顶堆则是最小值。

堆排序就是把堆顶的元素与最后一个元素交换,交换之后破坏了堆的特性,我们再把堆中剩余的元素再次构成一个大顶堆,然后再把堆顶元素与最后第二个元素交换….如此往复下去,等到剩余的元素只有一个的时候,此时的数组就是有序的了。

为方便理解我还准备了动图:

public class HeadSort {
    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 8, 100, 7, 9, 4, 20};
        int n = arr.length;
         //构建大顶堆
         for (int i = (n - 2) / 2; i >= 0; i--) {
             sort(arr, i, n - 1);
         }

         //进行堆排序
        for (int i = n - 1; i >= 1; i--) {
            // 把堆顶元素与最后一个元素交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            // 把打乱的堆进行调整,恢复堆的特性
            sort(arr, 0, i - 1);
         }

        CommonUtils.print(arr);
    }


    public static void sort(int[] arr,int parent, int n) {
        int child = 2*parent+1;

        while (child<n){

            //如果右节点大于左节点这把指针只想左节点
            if(child+1<n&&arr[child]<arr[child+1]){
                child++;
            }
            //比较子节点和父节点的大小
            if(arr[child]>arr[parent]){
                CommonUtils.swap(arr,child,parent);
            }
            parent = child;
            child = 2*parent+1;
        }
    }

}

总结

用一张图汇总了10大排序算法的性质

参考文章:

堆排序详细图解(通俗易懂)_右大臣的博客-CSDN博客 

https://www.cnblogs.com/itsharehome/p/11058010.html

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

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

相关文章

C++【STL】之priority_queue学习

优先级队列 优先级队列priority_queue也是STL库中容器适配器的一种&#xff0c;常用于进行数据优先级的处理&#xff0c;说到这儿是不是发现有些熟悉&#xff0c;没错它和我们之前讲解的堆本质上就是一个东西&#xff0c;底层都是数组存储的完全二叉树&#xff0c;它在STL库中…

设计模式(二十二):行为型之备忘录模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二、三)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(四)&#xff1a;创建型之原型模式 设计模式(五)&#xff1a;创建型之建造者模式 设计模式(六)&#xff1a;结构型之代理模式 设计模式…

华为OD机试真题 JavaScript 实现【最短木板长度】【2022Q4 100分】,附详细解题思路

一、题目描述 小明有 n 块木板&#xff0c;第 i ( 1 ≤ i ≤ n ) 块木板长度为 ai。 小明买了一块长度为 m 的木料&#xff0c;这块木料可以切割成任意块&#xff0c;拼接到已有的木板上&#xff0c;用来加长木板。 小明想让最短的木板尽量长。 请问小明加长木板后&#xff0c…

Android12之执行adb disable-verity后android无法启动(一百五十六)

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

前沿应用丨大规模无人机集群与“虚实结合”半实物仿真系统

一、应用背景 无人机集群在军事、安全、救援、航空监测、物流配送等领域具有广泛的应用前景。它可以提高任务执行的效率、灵活性和安全性&#xff0c;同时降低人力资源的需求和风险&#xff0c;无人机集群研究涉及多个学科领域&#xff0c;如机器人学、控制理论、通信技术和人工…

Verilog | 基4 booth乘法器

上接乘法器介绍 原理 跟基2的算法一样&#xff0c;假设A和B是乘数和被乘数&#xff0c;且有&#xff1a; A ( a 2 n 1 a 2 n ) a 2 n − 1 a 2 n − 2 … a 1 a 0 ( a − 1 ) B b 2 n − 1 b 2 n − 2 … b 1 b 0 \begin{align}A&(a_{2n1}a_{2n})a_{2n−1}a_{2n−2}……

【ARIMA-LSTM】合差分自回归移动平均方法-长短期记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于Nginx1.22+PHP8+MySQL8安装Discuz! X3.5

基于Nginx1.22PHP8MySQL8安装Discuz! X3.5 1. 安装PHP82. 安装MySQL83. 配置Nginx1.224. 安装Discuz! X3.5 1. 安装PHP8 更新系统&#xff1a; yum update安装EPEL存储库&#xff1a; yum install epel-release安装Remi存储库&#xff08;提供了最新的 PHP 版本&#xff09;&…

阿里云主机详解:ECS/轻量/虚拟主机/GPU/裸金属/云电脑详解

阿里云云主机分为云虚拟主机、云服务器ECS、轻量应用服务器、GPU云服务器、弹性裸金属服务器、专有宿主机、FPGA云服务器、高性能计算E-HPC、无影云电脑等&#xff0c;阿里云百科来详细说下阿里云云主机详解&#xff1a; 目录 阿里云云主机 云服务器ECS 轻量应用服务器 云…

python数字猜谜2.0

改进了一下数字猜谜&#xff1a; 开头&#xff0c;可选等级&#xff1a; import random guess -1 c 0 print("数字猜谜游戏&#xff01;") n input("选择等级 A B C&#xff1a;") if (n "A") or (n "a"):guess random.randint…

学习css样式的第二章

1.CSS 布局 - display 属性 display 属性是用于控制布局的最重要的 CSS 属性。 display 属性 display 属性规定是否/如何显示元素。 每个 HTML 元素都有一个默认的 display 值&#xff0c;具体取决于它的元素类型。大多数元素的默认 display 值为 block 或 inline 块级元素…

JavaEE课程设计——校园招聘管理系统(vue框架分析)

目录 Vue架构 登录 Vue架构 前端执行命令 npm run serve 这是整个前端的目录结构 vue.config.js是对前端vue的一个配置&#xff0c; // var webpack require(webpack); const path require(path)function resolve(dir) {return path.join(__dirname, dir) }function pu…

centos下的Nginx的安装

1.Nginx简介 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。其特点是占有内存少&#xff0c;并发能力强。 其他服务器介绍&#xff1a;Apache服务器、Tomcat服务器、Lighttpd服务器 2.nginx依赖安装 yum -y instal…

【数据分享】1929-2022年全球站点的逐月平均海平面压力数据(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 对于具体到监测站点的气象数据&#xff0c;之前我们分享过1929-2022年全球气象…

Opencv-C++笔记 (9) : opencv-多通道分离和合并

文章目录 一、概论二、多通道分离函数split()三、多通道合并函数merge()四、图像多通道分离与合并例程 一、概论 在图像颜色模型中不同的分量存放在不同的通道中&#xff0c;如果我们只需要颜色模型的某一个分量&#xff0c;例如只需要处理RGB图像中的红色通道&#xff0c;可以…

数据结构与算法之堆排序

目录 堆排序概述代码实现时间复杂度堆排序概述 堆排序(Heap Sort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。…

基于SSM的电影院购票系统开源啦

大家好&#xff0c;今天给大家带来一款SSM的电影院售票系统&#xff0c;非常不错的一个项目&#xff0c;学习javaweb编程必备。 下载地址在文末 1.SpringMVC Spring MVC属于SpringFrameWork的后续产品&#xff0c;已经融合在Spring Web Flow 里面。Spring 框架提供了构建 Web …

香橙派4 2. 驱动usb2.0芯片cy7c68013

0. 环境 - 香橙派4&#xff08;Orangepi4_2.1.2_ubuntu_bionic_desktop_linux4.4.179.img&#xff09; - EZ-USB FX2LP CY7C68013A USB 核心板 1. 下载FX3_SDK_1.3.4_linux EZ-USB™ FX3 Software Development Kit https://www.infineon.com/cms/en/design-support/tools/sdk…

实时在线云消费机、考勤门禁控制器、网络读卡器服务端C# Socket源码

消费机UDP通讯协议介绍&#xff1a; 设备向服务器发送的指令格式&#xff0c;每个字段用半角逗号(,)分隔。序号指令名称指令格式指令说明示例1响应服务器的搜索100,包序列号,终端IP,子网掩码,网关IP,远程电脑主机IP,端口号,终端硬件号响应电脑发出的搜寻局域网内所有终端设备指…

VCL界面控件DevExpress VCL v23.1.3全新首发 - 支持Windows 11新主题

DevExpress VCL Controls是Devexpress公司旗下最老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下…