Java重点之基于比较的七大排序

七大基于比较的排序

直接插入排序

思想:以双指针来进行遍历数组和寻找较小元素的操作,每次找到较小元素的时候就将其插入到前面的适当位置,当遍历完整个数组,并完成插入操作后,排序完成。

时间复杂度:最好情况:O(N)
最坏情况:O(N^2)
空间复杂度:O(1)
结论:当一组数据趋近于有序,适用于插入排序

public static void insertSort(int[] array) {
        //该循环实现对整个数组的遍历操作
        for (int i = 1; i < array.length; ++i) {

            //记录将被插入的元素(i下标元素)
            int tmp = array[i];
            //j指向i的前一个元素
            int j = i - 1;

            for (; j >= 0; j--) {
                //如果j指向的元素比被插入元素大,就往后移一位
                if (array[j] > tmp) {
                    array[j + 1] = array[j];
                } else {//否则就找到了插入位置,跳出该循环
                    break;
                }
            }

            //j+1即为插入位置
            array[j + 1] = tmp;
        }
}

希尔排序

思想:将数组不断分组再进行排序,当分组的长度为1时,进行的就是直接插入排序。

时间复杂度:O(N1.3 ~ N1.5)
空间复杂度:O(1)

public static void shellSort(int[] array) {
        int gap = array.length;
        while (gap > 1) {
            //gap为1时,就是直接插入排序
            gap = gap / 3 + 1;
            shell(array, gap);
        }
}
public static void shell(int[] array, int gap) {
        for (int i = gap; i < array.length; ++i) {
            int tmp = array[i];
            int j = i - gap;
            for (; j >= 0; j -= gap) {
                if (array[j] > tmp) {
                    array[j + gap] = array[j];
                } else {
                    break;
                }
            }
            array[j + gap] = tmp;
        }
}

选择排序

思想:选择排序是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,继续放在起始位置直到未排序元素个数为0。

时间复杂度:O(N2)

空间复杂度:O(N2)

public static void selectSort(int[] array){
    for(int i = 0;i<array.length;++i){
        for(int j = i+1;j<array.length;++j){
            if(array[j]<array[i]){
                int tmp = array[i];
                array[i] = array[j];
                array[j] = tmp;
            }
        }
    }
}

堆排序

思想:从小到大排序,就先建一个大堆,堆头元素就是整个数组中最大的数,==因此我们每次将堆头元素与堆尾元素交换,交换一次,堆尾下标往前移动一位,形成一个新堆,再向下调整构建成大堆;==以此循环,直到堆尾下标与堆头下标重合,堆排序完成。

时间复杂度:O(N*log N)

空间复杂度:O(1)

public static void heapSort(int[] array) {
        createHeap(array);//建大堆
        int end = array.length - 1;
    //将堆头元素与堆尾元素互换位置,就将最大元素放到了最后一位,舍去最后一位小标重新将堆向下调整;直到堆为空,数组中元素就排序完成。
        while (end >= 0) {
            int tmp = array[0];
            array[0] = array[end];
            array[end] = tmp;
            end--;
            siftDown(array, 0, end);
        }
    }
	//从小到大排序,建一个大堆
	public static void createHeap(int[] array) {
        for (int parent = (array.length - 1) / 2; parent >= 0; parent--) {
            siftDown(array, parent, array.length-1);
        }
    }

	//向下调整大堆
    public static void siftDown(int[] array, int root, int end) {
        int parent = root;
        int child = 2 * parent + 1;
        while (child <= end) {
            if (child + 1 <= end && array[child] < array[child + 1])
                child++;
            if (array[parent] < array[child]) {
                int tmp = array[parent];
                array[parent] = array[child];
                array[child] = tmp;
                parent = child;
                child = parent * 2 + 1;
            } else {
                break;
            }
        }
    }

冒泡排序

思想:相邻的元素两两比较,较大的数下沉,较小的数冒起来,这样一趟比较下来,最大(小)值就会排列在一端。该冒泡排序为优化过的排序,定义一个boolean类型的变量来判断数组是否已经有序,若有序可以直接返回,以此来减少时间复杂度。

时间复杂度:最坏:O(N2)

​ 最优:O(N)

空间复杂度:O(1)

 public static void bubbleSort(int[] array) {
     //最外层循环为比较的趟数
        for (int i = 0; i < array.length - 1; ++i) {
            //flag是为了判断接下来的循环是否有必要进行
            boolean flag = false;
            //内层循环为每趟比较的次数
            for (int j = 0; j < array.length - 1 - i; ++j) {
                if (array[j] > array[j + 1]) {
                    int tmp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = tmp;
                    flag = true;
                }
            }
            //flag==false说明这趟循环没有交换数据,也就是说数组已经有序,可以直接返回。
            if (flag == false) return;

        }
    }

快速排序

思想:先找到一个中间元素,将小于这个元素的数放到它的左边,大于这个元素的数放到它的右边,再将左右两部分进行上述操作,重复以往,就完成快排操作。
时间复杂度:最好:O(Nlog 2N)
最坏:O(N2)
时间复杂度平均:O(Nlog2N)
空间复杂度:O(Nlog2N)

public static void quickSort(int[] array, int l, int r) {
        if (l >= r) return;
    //因为用do while()循环,所以先将左右指针向两边移动一位
        int i = l - 1, j = r + 1;
    //取数组中间元素的值作为这个分割点
        int mid = array[(l + r)>>1];

        while (i < j) {
            //左边的数小于中间值,指针向右移动
            do ++i; while (array[i] < mid);
            //右边的数大于中间值,指针向左移动
            do --j; while (array[j] > mid);
            //两个指针停下后交换元素
            if (i < j) {
                int tmp = array[i];
                array[i] = array[j];
                array[j] = tmp;
            }

        }
    //递归左半部分
        quickSort(array, l, j);
    //递归右半部分
        quickSort(array, j + 1, r);

    }

归并排序

思想:先分组再排序,和快排操作顺序相反。将数组分为左右两部分,再对左右两部分 分别再分组,以此类推,直到每一部分只有一个元素,然后按顺序合并为一个个新的有序数组,小数组归并为大数组,以此类推就得到排序后的数组。

时间复杂度:O(N*logN)

空间复杂度:O(N)

 public static void mergeSort(int[] array){
        mergerSortInternal(array,0,array.length-1);
    }
    public static void mergerSortInternal (int[] array,int l,int r){
        if(l>=r)    return;
        int mid = (l+r)>>1;
        //递归左半部分
        mergerSortInternal(array,l,mid);
        //递归右半部分
        mergerSortInternal(array,mid+1,r);
        //归并
        merge(array,l,mid,r);
    }
    public static void merge(int[] array,int l,int mid, int r){
        int s1 = l,e1 = mid;
        int s2 = mid+1, e2 = r;
        int [] tmp = new int[r-l+1];
        int k = 0;
        //比较两个有序小数组元素,将小的元素放到新数组前面,大的元素放到新数组后面
        while(s1<=e1 && s2<=e2){
            if(array[s1]<array[s2]){
                tmp[k++] = array[s1++];
            }else{
                tmp[k++] = array[s2++];
            }
        }
        //处理剩余元素
        while(s1<=e1)   tmp[k++] = array[s1++];
        while(s2<=e2)   tmp[k++] = array[s2++];
        //将排完序的新数组元素放回原数组中
        for(int i = 0;i<tmp.length;++i){
            array[i+l] = tmp[i];
        }
    }

到此这篇关于Java重点之基于比较的七大排序的文章就介绍到这了,更多相关Java 排序内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java实现两个随机数组合并进行排序的方法

    目录 前言: 一.什么是线性表 二.ArrayList集合 三.用线性表的思想排序数组间排序 四.冒泡排序: 前言: ​ 小Du猿结束"996ICP"CRUD开发工作生活,重新进入了校园学习生活.本周开始了第二周数据结构的基础知识学习,大爱向宇老师的上课方式,用生动形象的方式讲解抽象概念,但一开口就是LSP.O(∩_∩)O,向向宇大佬致敬,菜鸡小Du猿投来膜拜的眼光. ​ 此博客用Java实现线性表的思想,实现数组的排序和序列化.序列化的排序方式采用冒泡排序的方式,但小Du猿正在优化该

  • Java排序的那些事之sort方法的使用详解

    目录 引言 升序 数组 集合 降序 声明一个类实现接口 匿名内部类实现接口 Lambda表达式实现接口 自定义数据类型的排序 总结: 引言 在学习Java过程中,排序sort是我们常用的功能:在Java里,数组有Arrays.sort()可以排序,集合则是Collections.sort()方法排序:默认情况下是升序排列,但是降序又该怎么排?又可以通过哪几种方法呢?自定义类型又该怎么做? 下面就来介绍一下sort方法的使用: 升序 升序是默认情况下的,所以这里就简单展示一下使用的方法: 数组 数

  • JAVA十大排序算法之基数排序详解

    目录 基数排序 代码实现 时间复杂度 算法稳定性 基数排序 vs 桶排序 vs 计数排序 总结 基数排序 常见的数据元素一般是由若干位组成的,比如字符串由若干字符组成,整数由若干位0~9数字组成. 基数排序按照从右往左的顺序,依次将每一位都当做一次关键字,然后按照该关键字对数组排序,同时每一轮排序都基于上轮排序后的结果:当我们将所有的位排序后,整个数组就达到有序状态.基数排序不是基于比较的算法. 基数是什么意思?对于十进制整数,每一位都只可能是0~9中的某一个,总共10种可能.那10就是它的基,

  • JAVA十大排序算法之桶排序详解

    目录 桶排序 代码实现 时间复杂度 算法稳定性 总结 桶排序 桶排序是计数排序的升级,计数排序可以看成每个桶只存储相同元素,而桶排序每个桶存储一定范围的元素,通过函数的某种映射关系,将待排序数组中的元素映射到各个对应的桶中,对每个桶中的元素进行排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序),最后将非空桶中的元素逐个放入原序列中. 桶排序需要尽量保证元素分散均匀,否则当所有数据集中在同一个桶中时,桶排序失效. 代码实现 1.找出数组中的最大值max和最小值min,可以确定出数组所在范

  • Java数据结构之基于比较的排序算法基本原理及具体实现

    目录 1. 七大基于比较的排序-总览 1.1常见基于比较的排序分类 1.2时间复杂度,空间复杂度以及稳定性. 2.直接插入排序 2.1 直接插入排序的基本思想 2.2 直接插入排序动画演示 2.3 代码示例 2.4 时间复杂度,空间复杂度以及稳定性 3. 希尔排序 3.1 算法思想 3.2 图片演示 3.3 代码示例 3.4 时间复杂度,空间复杂度以及稳定性 4.选择排序 4.1 算法思想 4.2 动画演示 4.3 代码示例 4.4 时间复杂度,空间复杂度以及稳定性 5.堆排序 5.1 算法思想

  • Java重点之基于比较的七大排序

    七大基于比较的排序 直接插入排序 思想:以双指针来进行遍历数组和寻找较小元素的操作,每次找到较小元素的时候就将其插入到前面的适当位置,当遍历完整个数组,并完成插入操作后,排序完成. 时间复杂度:最好情况:O(N) 最坏情况:O(N^2) 空间复杂度:O(1) 结论:当一组数据趋近于有序,适用于插入排序 public static void insertSort(int[] array) { //该循环实现对整个数组的遍历操作 for (int i = 1; i < array.length; +

  • Java 数据结构七大排序使用分析

    目录 一.插入排序 1.直接插入排序 2.希尔排序 二.选择排序 1.选择排序 2.堆排序 三.交换排序 1.冒泡排序 2.快速排序 四.归并排序 五.排序算法的分析 一.插入排序 1.直接插入排序 当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]与array[i-1],array[i-2],…进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移. 数据越接近有序,直接插入排序的时间消耗越少.

  • 浅析Java中接口和抽象类的七大区别

    目录 接口 抽象类 区别1:定义关键字不同 区别2:继承或实现的关键字不同 区别3:子类扩展的数量不同 区别4:属性访问控制符不同 区别5:方法控制符不同 区别6:方法实现不同 区别7:静态代码块使用不同 总结 Java 是一门面向对象的编程语言,面向对象的编程语言有四大特征:抽象.封装.继承和多态. 而本文介绍的接口和抽象类就是面向对象编程中"抽象"的具体实现,也就是说接口和抽象类都是用来定义实体类的公共行为的,它们是对实体类(对象)更高层次的抽象. ​说明:本文以下内容基于 JDK

  • Java编程实现汉字按字母顺序排序的方法示例

    本文实例讲述了Java编程实现汉字按字母顺序排序的方法.分享给大家供大家参考,具体如下: String[] str0 = new String[]{"abd","ervcd","sdfc","abdc","sded","生活","文教","政治"}; String[] str1 = new String[]{"生活","

  • Java实现拖拽列表项的排序功能

    在一些允许用户自定义栏目顺序的app(如:凤凰新闻.网易云音乐等),我们可以方便地拖拽列表项来完成列表的重新排序,进而完成对栏目顺序的重排.这个功能很人性化,而实现起来其实很简单(甚至都不用写什么后台代码),只有三步. ①把冰箱门打开 首先,我们需要让冰箱的大门敞开,也就是允许我们进行拖拽的相关操作.以ListView为例,注意下面几个属性. <StackPanel> <ListView x:Name="list" AllowDrop="True"

  • java中实现Comparable接口实现自定义排序的示例

    实例如下所示: class Student implements Comparable{ String name; int gpa; @Override public int compareTo(Object arg0) { // TODO Auto-generated method stub Student s = (Student)arg0; if(gpa == s.gpa) return name.compareTo(s.name); else if(gpa < s.gpa) return

  • java开发中基于JDBC连接数据库实例总结

    本文实例讲述了java开发中基于JDBC连接数据库的方法.分享给大家供大家参考,具体如下: 创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class类的静态方法forName(String  className)实现. 例如: try{ //加载MySql的驱动类 Class.forName("com.mysql.jdbc.Driver") ; }c

  • java编程实现基于UDP协议传输数据的方法

    本文实例讲述了java编程实现基于UDP协议传输数据的方法.分享给大家供大家参考,具体如下: UDP协议(User Datagram Protocol,用户数据报协议)不同于TCP协议,它是不可能靠的,但是它比TCP协议具有更快的传输速度,UDP发送的数据单元称为数据报,当网络传输UDP传输UDP数据报是无法保证数据能够到达目的地,也无法保证按发送的顺序到达目的地,也就是说先发送了"hello",再发送了"world",但接收方可能会先收到"world&q

  • java数据结构与算法之简单选择排序详解

    本文实例讲述了java数据结构与算法之简单选择排序.分享给大家供大家参考,具体如下: 在前面的文章中已经讲述了交换类的排序算法,这节中开始说说选择类的排序算法了,首先来看一下选择排序的算法思想: 选择排序的基本算法思想: 每一趟在 n-i+1 (i=1,2,3,--,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录. 简单选择排序: 设所排序序列的记录个数为n.i取1,2,-,n-1,从所有n-i+1个记录(Ri,Ri+1,-,Rn)中找出排序码最小的记录,与第i个记录交换.执行n-

随机推荐