十大排序笔记Java实现

十大排序

秋招准备笔试,发现排序很不熟练,特意花一下午复习一下排序。

排序分为两种,内部排序和外部排序。

  • 内排序:待排序序列完全存放在内存中进行的排序过程,这种方法适合数量不太大的数据元素的排序。
  • 外排序:待排序元素非常多,以至于必须存放在外部存储器中,这种排序过程需要访问外存储器。

内排序都是一个逐步扩大记录的有序序列长度的过程。内部排序方法大致可分为:

  • 插入类:将无序子序列中的一个或几个记录插入到有序序列中,从而增加记录的有序子序列的长度。
  • 交换类:通过交换无序序列中的记录,从而得到其中关键字最小或最大的记录,并将它加入有序子序列中。
  • 选择类:从记录的无序子序列选择关键字最小或最大的记录,并将它们加入有序子序列中。
  • 归并类:通过归并两个或两个以上的记录有序子序列,逐步增加记录有序序列的长度。
  • 其他类

插入排序

直接插入排序

基本思想:每趟将一条待排序的记录,按其关键字的大小插入到前面已排好序的记录序列中的适当位置,知道全部记录插入完成为止。
基本要求:假设待排序的记录存放在数组中,开始时将第0个记录组成一个有序的子表,然后依次将后面的记录插入到这个子表中,并且一致保持子表的有序性。

  • 不带监视哨的直接插入排序:
 public static int[] StraightInsertionSort(int []str){
        int i , j;
        j = 0;
        for(i = 1 ; i < str.length ; i ++){
            int temp = str[i];
            for(j = i-1 ; j>=0 && temp<str[j] ;j--){
                str[j+1] = str[j];
            }
            str[j+1] = temp;
        }
        return str;
    }

结果:在这里插入图片描述

  • 带监视哨的直接插入排序:
    将str[0]作为监视哨,在不带监视哨的插入排序中,判断条件比较复杂:j>=0 && temp<str[j] 改进:将temp的值存放进str[0],这样,当扫描至str[0]时,二值相等,自然就不满足循环条件,因此结束循环,这样就不需要判断下标是否越界了。
    带监视哨的插入排序有一个问题:因为将str[0]作为监视哨来优化效率,因此str[0]中是不存放有效记录的,长度n的顺序表中实际上只能存储n-1个记录。
 //带监视哨的直接插入排序
    public static int[] SISwithGuard(int[] str){
        int i , j ;
        for(i = 2 ; i < str.length ; i++){
            int temp = str[i];
            str[0] = temp;
            for(j = i -1 ; temp < str[j] ; j-- ){
                str[j+1] = str[j];
            }
            str[j+1] = temp;
        }
        return str;
    }

结果:str[0]为52,因为str[0]作为监视哨,所以那个52没参与排序。
在这里插入图片描述

性能分析

空间复杂度:O(1)
时间复杂度:O(n²)

希尔排序

基本思想:先选取一个小于n的整数d(增量),然后把排序表中的n个记录分为d个子表,从下表为0的记录开始,间隔为d的记录组成一个子表,在各个子表内进行直接插入排序,在一趟之后,间隔为d的记录组成的子表已经有序,随着有序性的改善,逐步减少d,直到d==1。

public void shellsort(int[] d) {//d为增量数组
        RecordNode temp;
        int i, j;
        for (int k = 0; k < d.length; k++) {
            int dk = d[k];
            for (i = dk; i < this.curlen; i++) {
                temp = r[i];
                for (j = i - dk; j >= 0 && temp.key.compareTo(r[j].key) < 0; j -= dk) {
                    r[j + dk] = r[j];
                }
                r[j + dk] = temp;
            }
        }
    }
  • 希尔排序最后一次增量一定是1
  • 分割后子序列内部排序算法为直接插入排序

交换排序

冒泡排序

基本思想:将待排序数组看成从上到下排放,把关键字值较小的记录看成“较轻的”,关键字值较大的看成“较重的”。较小关键字的记录就像气泡,向上浮,较大关键字值的记录向下。
注意点:需要一个flag变量来判断此轮遍历是否有交换,如果没有交换直接break,结束排序。

public static int[] BubbleSort(int[] str){
        int i ,j;
        boolean flag = true;
        for(i = 1 ; i < str.length && flag ; i ++ ){
            flag = false;
            for(j = 0 ; j < str.length-i ; j++){
                if(str[j+1] > str[j]){
                    int temp;
                    temp = str[j];
                    str[j] = str[j+1];
                    str[j+1] = temp;
                    flag = true;
                }
            }

        }
        return str;
    }

快速排序

分治策略:将原问题划分成若干个规模较小但与原问题相似的子问题,然后再递归。
基本思想:通过一趟排序将要排序的记录分割成独立的两个部分,其中一个部分的所有记录的关键字值都比另外一部分的所有记录关键字小,然后再按此方法对两部分记录分别进行快速排序,整个排序过程递归进行。

 public static int Partition(int i,int j){
        RecordNode pivot = r[i];
        while(i<j){//从表的两端交替的向中间扫描
            while(i<j && pivot.key.compareTo(r[j].key) <= 0){
                j--;
            }
            if(i<j){
                r[i]=r[j];
                i++;
            }
            while (i<j && pivot.key.compareTo(r[i].key)>0){
                i++;
            }
            if(i<j){
                r[j] = r[i];
                j--;
            }
        }
        r[i] = pivot;
        return i;
    }
    public static void qSort(int low,int high){
        if(low<high){
            int pivotloc = Partition(low,high);
            qSort(low,pivotloc-1);
            qSort(pivotloc+1,high);
        }
    }
    public static void quicksort(){
        qSort(0,this.curlen);
    }

选择排序

主要思想:每一趟从待排序列中选取一个关键字值最小的记录。

直接选择排序

直接选择排序(Straight Selection Sort)的基本思想是:在第1趟中,从n个记录中找出关键字值最小的记录与第1个记录交换;在第2趟中,从第2个记录开始的n-1个记录中再选出关键字值最小的记录与第二个记录交换;以此类推,在第i趟中,从第i个记录开始的n-i+1个记录中选出关键字值最小的记录与第i个记录交换,直到整个序列按关键字值有序为止。

public static int[] StraightSelect(int[] str){
        int i,j;
        for(i = 0 ; i < str.length -1; i ++){
            int min = i;
            for(j = i+1 ; j < str.length ; j++){
                if(str[j] < str[min]){
                    min = j ;
                }
            }
            if(min != i){
                int temp = str[i];
                str[i] = str[min];
                str[min] = temp;
            }
        }
        return str;

树形选择排序

(有点像带备忘录的递归)

堆排序

堆排序
升序用大根堆,降序就用小根堆
构建堆:
主要思路:第一次保证00位置大根堆结构(废话),第二次保证01位置大根堆结构,第三次保证02位置大根堆结构…直到保证0n-1位置大根堆结构(每次新插入的数据都与其父结点进行比较,如果插入的数比父结点大,则与父结点交换,否则一直向上交换,直到小于等于父结点,或者来到了顶端)

归并排序

归并:将两个或两个以上的有序表合并成一个新的有序表。其中,将两个有序表合并成一个有序表的归并排序称为二路归并排序,否则称为多路归并排序。

二路归并

核心操作:将两个相邻的有序序列归并成一个有序序列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 狂神说Java全部笔记是一部非常受欢迎的Java学习资料。这份笔记主要由狂神根据自己多年的Java开发经验总结而成,包含了Java开发中的各个方面。 首先,笔记中涵盖了Java的基础知识,如Java的发展历史、安装配置、基本语法、数据类型、运算符等。这些内容对于初学者来说非常重要,可以帮助他们快速入门。 其次,笔记中还介绍了Java的面向对象编程思想,包括封装、继承、多态等概念,以及如何使用类、对象、方法等构建自己的程序。这是Java开发的核心内容,通过深入学习这些知识,可以更好地掌握Java编程。 此外,狂神还在笔记中详细介绍了Java中常用的类库和API,如集合框架、IO操作、多线程、网络编程等。这些内容对于提升开发效率和扩展能力非常有帮助。 最后,笔记中还包含了一些实战项目的案例分析,可以帮助读者将所学的知识应用到实际项目中。通过动手实践,读者可以更好地理解和掌握Java开发的各个环节。 总的来说,狂神说Java全部笔记是一份非常全面和实用的学习资料,适合各个阶段的Java学习者。无论是初学者还是有一定经验的开发者,都可以从中获益良多。通过学习这份笔记,读者可以打下良好的Java基础,掌握Java开发的核心知识,提高开发能力,从而更好地应对实际项目的需求。 ### 回答2: 狂神说Java是一份关于Java编程语言的全面笔记,内容涵盖了Java的基础知识、面向对象编程、集合框架、多线程编程、Java IO、数据库编程等方面的内容。 在Java的基础知识部分,狂神详细介绍了Java的发展历史、Java的安装配置、Java的数据类型、运算符、控制语句等基本知识,并给出了许多实际案例进行演示和讲解,帮助读者理解和掌握这些概念和技能。 在面向对象编程部分,狂神详细介绍了Java中的类和对象、封装性、继承性、多态性等面向对象的特性,以及如何利用这些特性进行软件开发,包括类的设计、构造方法、方法重载和方法重写等内容。 在集合框架部分,狂神讲解了Java中的各种集合类,如ArrayList、LinkedList、HashMap等,并介绍了它们的使用方法和常见应用场景,以及集合的遍历和排序等相关操作。 在多线程编程部分,狂神详细介绍了Java中的线程概念、线程的创建和启动、线程同步与通信等内容,并提供了一些实际案例来演示多线程编程的实际应用。 在Java IO部分,狂神讲解了Java中的输入输出流、文件操作、字符流和字节流等内容,并提供了一些示例代码进行演示。 在数据库编程部分,狂神介绍了Java中如何使用JDBC进行数据库的连接和操作,包括建立连接、执行SQL语句、事务处理等内容,并提供了一些实际案例进行演示。 总之,狂神说Java是一份非常全面、详细的Java编程笔记,适合初学者和有一定基础的Java开发者阅读和学习。通过阅读狂神说Java,读者可以系统地了解和掌握Java编程的基本知识和技能,为以后的Java开发打下良好的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值