选择,插值,希尔排序算法的泛型排序实现

一、选择排序

1、思想

我们一定要理解选择排序的思想,假设是按着升序排序的方式,

  • 首先找到最小的数,然后将第一个数组的第一个数据和它进行交换
  • 然后找到第二个小的数,将它和数组的第二个树进行交换
  • 依次下去

2、代码

  • 这里我们使用了Comparable接口,这样的好处是,当我们自定义的类只要实现了Comparable接口,并且实现compareTo方法都可以调用这算法来进行排序
package cn.mldn;


public class SelectionSort {
    public static void main(String[] args) {
        Integer[] j = {10,7,4,5,2,9};
        show(j);
        sort(j);
        show(j);
    }

    private static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }

    private static void exch(Comparable[] a,int i, int j) {
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    private static void show(Comparable[] a) {
        for(int i = 0;i < a.length;i++) {
            System.out.print(a[i] + "郑光光");
        }
        System.out.println();
    }

    public static boolean isSorted(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            if (less(a[i],a[i-1])) {
                return false;
            }
        }
        return true;
    }

    private static void sort(Comparable[] a) {
        int N = a.length;
        for (int i = 0; i < N; i++) {
            int min = i;
            //当i = 1的时候,这个内部的for循环结束后就找到了最小的数
            //当i = 2的时候,这个内部的for循环结束后就找到了第二小的数的数
            for (int j = i + 1; j < N; j++) {
                if (less(a[j],a[min])) {
                    min = j;
                }
            }
            //所以我们的交换应该写到这来
            exch(a, i, min);
        }
    }
}

3、补充知识

今天在用dos命令启动java文件的时候一直报错,所以我又去复习的一遍,你如果看我这篇文章也跟我来一起吧。

  • 首先来看我创建的java文件的位置【在cn和mldn不是目录,是我在项目里面的包】
    在这里插入图片描述
  • 当我进入到这个目录
    在这里插入图片描述
    报了一个错【这个错误不影响啥,先往后面看】
    在这里插入图片描述
  • 然后再执行下面的【我感觉没问题啊】
    在这里插入图片描述
  • 但是不要忘记的我们的【这里面重复了】
    在这里插入图片描述
  • 应该回退这样执行
    在这里插入图片描述
    ok了没事了

二、插值排序(插入排序)

1、一定要理解的思路

  • 插值排序是将一个待排序的数组,将其分为两部分,假设我们选择下标为x的点进行分割,要对x和x前面部分进行排序,每次插入的下一个x,依次下去

2、代码

package cn.mldn.Insertion;

public class InsertionSort {
    public static void main(String[] args) {
        Integer[] j = {10,7,4,5,2,9};
        show(j);
        InsertedSort(j);
        show(j);
    }

    private static boolean less(Comparable a, Comparable b) {
        return a.compareTo(b) < 0;//说明a小于b
    }

    //满足的情况下就交换
    private static void exch(Comparable[] c,int i,int j) {
        Comparable t = c[i];
        c[i] = c[j];
        c[j] = t;
    }

    //用于显示数组中的内容
    private static void show(Comparable[] c) {
        int N = c.length;
        for (int i = 0; i < N; i++) {
            System.out.print(c[i] + " ");
        }
        System.out.println();
    }

    private static boolean isSorted(Comparable[] c) {
        for (int i = 0; i < c.length; i++) {
            if (less(c[i],c[i-1])) {
                return false;
            }
        }
        return true;
    }

    private static void InsertedSort(Comparable[] c) {
        for (int i = 1; i < c.length; i++) {
            for (int j = i; j > 0 ; j--) {
                if (less(c[j], c[j-1])) {
                    exch(c, j, j - 1);
                }
            }
        }
    }
    private static void InsertedSort2(Comparable[] c) {
        for (int i = 1; i < c.length; i++) {
            for (int j = i; j > 0 && less(c[j], c[j-1]) ; j--) {
                exch(c, j, j - 1);
            }
        }
    }
}

三、前面两种算法的比较

1、图解过程

在这里插入图片描述

2、测试一下时间复杂度

  • 以后的时间复杂度的测试都是这样编写了,如果你电脑比较牛逼的话,你可以把这个N的值变大一点,而且你如果愿意等的话,我电脑不够牛逼,所以为八万
public static void main(String[] args) {
        int N = 80000;
        Integer[] j = new Integer[N];
        for (int i = 0; i < N; i++) {
            j[i] = (int)Math.random()*N;
        }
        long l = System.currentTimeMillis();
        sort(j);
        long e = System.currentTimeMillis();
        System.out.println("所用时间为:" + (e - l));
    }
  • 看结果
    在这里插入图片描述
    在这里插入图片描述
  • 原因:选择排序的时间复杂度为N(N - 1)/ 2 ~ N*N /2,而我们的插值排序的算法的时间复杂度为N

四、希尔排序

1、思路

首先这个很重要,很重要的:它其实就是外部先将数组分成若干个数组,又进行了插值排序【一定要记得它内部还是一个插值排序的过程】

2、代码实现

import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int N = 8;
        Integer[] j = {10,2,4,6,8,9,3};
        show(j);
        /*for (int i = 0; i < N; i++) {
            j[i] = new Integer ((int)Math.random()*N);
        }*/
        ShellSort(j);
        show(j);
        /*long l = System.currentTimeMillis();
        sort(j);
        long e = System.currentTimeMillis();
        System.out.println("所用时间为:" + (e - l));*/
    }

    private static void show(Comparable[] a) {
        for(int i = 0;i < a.length;i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }

    private static boolean less(Comparable a , Comparable b) {
        return a.compareTo(b) < 0;
    }

    private static void exch(Comparable[] c, int i, int j) {
        Comparable t = c[i];
        c[i] = c[j];
        c[j] = t;
    }

    //这个版本是跟着书上敲代码的,你如果能看懂那就看这个,如果看不懂就跟着我下面的理解或许可以
    private static void sort(Comparable[] c) {
        int N = c.length;
        int h = 1;
        while (h < N/3) {
            h = 3 * h + 1;
        }
        while(h >= 1) {
            for (int i = h; i < N; i++) {
                for (int j = i; j >=h; j-=h) {
                    if (less(c[j],c[j-h])) {
                        exch(c,j,j-h);
                    }
                }
            }
            h = h / 3;
        }
    }

    //这个是我自己能理解的版本
    public static void ShellSort(Comparable[] arr) {
        //通过这个循环我找到了步长
        for (int k = arr.length / 2; k > 0; k = k / 2) {
            //通过上面的步长我找到了第一个位置【数组下标为0的个往后移动了步长的那个点】
            for (int i = k; i < arr.length; i++) {
                //仔细一看,这个内部其实就是一个查找排序,只是它移动的步长不是1而已,所以不能理解先去理解上面的插值排序
                for (int j = i - k; j  >= 0; j -= k) {
                    //如果当前元素大于加上步长的那个元素,则交换
                    if (less(arr[j+k],arr[j])) {
                        exch(arr,j+k,j);
                    }
                }
            }
        }

    }



}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值