数据结构与算法-排序

目录

Comparable 接口

1、简单排序

1.1、冒泡排序

1.2、选择排序

1.3、插入排序

2、高级排序

2.1 希尔排序

2.2归并排序

2.3快速排序


Comparable 接口

  • 要比较的类实现Comparable接口
  • class Student implements Comparable<Student>
  • 重写compareTo方法
@Override
public int compareTo(Student o) {
    return this.getAge()-o.getAge();
}
package test.comparable;

public class Student implements Comparable<Student>{
    private int age;
    private  String name;

    public Student() {
    }

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    public int compareTo(Student o) {
        return this.getAge()-o.getAge();
    }
}
package test.comparable;

public class Test {

    public static void main(String[] args) {
        Student st1 = new Student(3,"lisan");
        Student st2 = new Student(4,"王四");
        Comparable cc = getMax(st1,st2);
        System.out.println(cc);
    }

    public static Comparable getMax(Comparable c1,Comparable c2){
        int i = c1.compareTo(c2);
        if(i>=0){
            return c1;
        }else{
            return c2;
        }
    }
}

输出:

Student{age=4, name='王四'}

1、简单排序

1.1、冒泡排序

package test.comparable;

public class Bubble {
    /*
    对数组a进行排序
     */
    private static void sort(Comparable<?> [] a){
        for (int i = a.length-1; i>0 ; i--) {
            for (int j = 0; j <i ; j++) {
                if(greater(a[j],a[j+1])){
                    exch(a,j,j+1);
                }
            }
        }
    }

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

    /**
     * 数组元素i和j交换位置
     * @param a
     * @param i
     * @param j
     */
    private static  void exch(Comparable<?>[]a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

}

测试代码

package test.comparable;

import java.util.Arrays;

public class Test {

    public static void main(String[] args) {
      Integer [] a = {4,5,3,7,8,2,1};
      Bubble.sort(a);
      System.out.println(Arrays.toString(a));

    }
}

冒泡排序时间复杂度分析

1.2、选择排序

选择排序的api设计

类名sefection
构造方法Selection();创建Selection对象
成员方法

1、public static void sort(Comparable<?> [] a)对数组内的元素进行排序

2、private static boolean greater(Comparable v,Comparable w)判断V是否大于W

3、private static void exch(Comparable<?>[]a,int i,int j);交换a数组中索引i和索引j处的值

package test.comparable;

public class Selection {
    /*
       对数组a进行排序
        */
    public static void sort(Comparable<?> [] a){
        for (int i = 0; i <a.length-1 ; i++) {
            int minIndex = i;
            for (int j = i+1; j <a.length ; j++) {
                if(greater(a[minIndex],a[j])){
                    minIndex = j;
                }
            }
            exch(a,minIndex,i);
        }
    }
    private static boolean greater(Comparable v,Comparable w){
        return  v.compareTo(w)>0;
    }

    /**
     * 数组元素i和j交换位置
     * @param a
     * @param i
     * @param j
     */
    private static  void exch(Comparable<?>[]a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

}



/**测试代码
*/
public class Test {

    public static void main(String[] args) {
      Integer [] a = {4,5,3,7,8,2,1};
      Selection.sort(a);
      System.out.println(Arrays.toString(a));

    }
}

1.3、插入排序

package test.comparable;

public class Insertion {

    /*
   对数组a进行排序
    */
    public static void sort(Comparable<?> [] a){
        for (int i = 1; i<a.length ; i++) {
            for (int j = i; j >0 ; j--) {
                if(greater(a[j-1],a[j])){
                    exch(a,j-1,j);
                }else{
                    break;
                }
            }
        }
    }


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

    /**
     * 数组元素i和j交换位置
     * @param a
     * @param i
     * @param j
     */
    private static  void exch(Comparable<?>[]a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

}

2、高级排序

2.1 希尔排序

 增长量h的确定:增长量h的值每一固定的规则,我们这里采用以下规则:

int h =1

while(h<数组的长度/2){

  h = 2h+1

}

//循环后我们可以获取h的最大值

h的减小规则为

h=h/2;

希尔排序的api设计

类名Shell
构造方法Shell();创建Selection对象
成员方法

1、public static void sort(Comparable<?> [] a)对数组内的元素进行排序

2、private static boolean greater(Comparable v,Comparable w)判断V是否大于W

3、private static void exch(Comparable<?>[]a,int i,int j);交换a数组中索引i和索引j处的值

package test.comparable;

public class Shell {

    /*
对数组a进行排序
 */
    public static void sort(Comparable [] a){
      //1、根据数组的长度,确定正常量h的初始值
        int h =1;
        while(h<(a.length/2)){
            h=2*h+1;
        }
        //2、希尔排序
        while(h>=1){
            //排序
            for(int i=h;i<a.length;i++){
                for(int j=i;j>=h;j-=h){
                    if(greater(a[j-h],a[j])){
                        exch(a,j-h,j);
                    }else{
                        //待插入的数据以及找到合适的
                        break;
                    }
                }
            }
            //
            //减小h的值
            h=h/2;
        }
    }


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

    /**
     * 数组元素i和j交换位置
     * @param a
     * @param i
     * @param j
     */
    private static  void exch(Comparable<?>[]a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

希尔排序的时间复杂度不好计算,但是比插入排序快很多

2.2归并排序

 排序原理

1、尽可能地把一组数据分成俩个元素相等的子组,并对每个子组继续拆分,直到拆分后的每个子组个数是1为止。

2、将相邻的俩个子组进行合并成一个有序的大组。

3、不断地重复操作,直到最终只有一个组为止。

归并排序api设计:

类名Merge
构造方法Merge();创建Merge对象
成员方法
1、public static void sort(Comparable<?> [] a);对数组内的元素进行排序

2、private static void sort(Comparable [] a,int lo,int hi);

对数组a中从lo到hi的元素进行排序

3、

private static void merge(Comparable[] a , int lo,int mid , int hi)
对数组中,从lo到min为一组,从min+1到hi为一组,对着俩组数据进行归并

4、

private static boolean less(Comparable v,Comparable w)
比较v大小是否小于w大小

5、

private static  void exch(Comparable<?>[]a,int i,int j)
数组元素i和j交换位置
成员变量1、private static Comparable[] assist;完成并归操作需要的辅助数组

package test.comparable;

/**
 * 归并排序
 */
public class Merge {
    //归并所需要的辅助数组
    private static Comparable[] assist;

    /**
     * 比较v大小是否小于w大小
     * @param v
     * @param w
     * @return
     */
    private static boolean less(Comparable v,Comparable w){
        return v.compareTo(w)<0;
    }


    /**
     * 数组元素i和j交换位置
     * @param a
     * @param i
     * @param j
     */
    private static  void exch(Comparable<?>[]a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    /**
     * 对数组a中的元素进行排序
     * @param a
     */
    public static void sort(Comparable [] a){
        //1、初始化辅助数组
        assist = new Comparable[a.length];
        //2、定义一个lo变量,和hi变量,分别记录数组中最小索引和最大索引;
        int lo = 0;
        int hi = a.length-1;
        //3、调用sort重载方法完成数组a中,从索引lo到索引hi的排序
        sort(a,lo,hi);

    }

    /**
     * 对数组a中从lo到hi的元素进行排序
     * @param a
     * @param lo
     * @param hi
     */
    public static void sort(Comparable [] a,int lo,int hi){
        //做安全性校验
        if(hi<=lo){
            return;
        }
        int mid =lo+(hi-lo)/2;
        sort(a,lo,mid);
        sort(a,mid+1,hi);
        merge(a,lo,mid,hi);

    }

    /**
     * 对数组中,从lo到min为一组,从min+1到hi为一组,对着俩组数据进行归并
     * @param a
     * @param lo
     * @param mid
     * @param hi
     */
    private static void merge(Comparable[] a , int lo,int mid , int hi){
        //1、定义三个指针
        int i=lo;
        int p1=lo;
        int p2=mid+1;
        //2、遍历、移动p1指针和p2指针,比较对应索引处的值,找到小的那个,放到辅助数组的对于索引处
        while(p1 <= mid && p2 <=hi){
            if(less(a[p1],a[p2])){
                assist[i++]=a[p1++];
            }else{
                assist[i++]=a[p2++];
            }
        }
        //3、如果p1没有走完,那么顺序移动p1指针,把对应的元素放到辅助数组的对应索引处

        while(p1<=mid){
            assist[i++]=a[p1++];
        }

        //4、如果p2没有走完,那么顺序移动p2指针,把对应的元素放到辅助数组的对应索引处
        while(p2<=hi){
            assist[i++]=a[p2++];
        }
        //把辅助数组的数据考呗到原数组中
        for (int index = lo; index <=hi ; index++) {
            a[index]=assist[index];
        }

    }

}

2.3快速排序

需求

排序前:{6,1,2,7,9,3,4,5,8}

排序后:{1,2,3,4,5,6,7,8,9}

排序原理:

1、首先设定一个分界值,通过读分界值件数组分成左右俩个部分

2、将大于或等于分界值的数据放到数组右边,小于分界值的数据放到数组左边,此时左边部分各元素小于或等于分界值,而右边部放置较大值,有车的数组数据也可以做类似处理。

3、重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序,当左侧和右侧俩个部分的数组排好序后,整个数组的排序也就完成了。

快速排序api设计

类名Quick
构成方法Quick();创建Quick对象
成员方法

切分原理:

把一个数组切分成俩个子数组的基本思想

1、找一个基准值,用俩个指针分别指向数组的头部和尾部;

2、先把尾部向头部开始收索一个比基准值小的元素,收索到即停止,并记录指针的位置。

3、再从头部向尾部开始收索一个比基准值大的元素,收索到即停止,并记录指针的位置。

4、交换当前左边指针位置和右边指针位置的元素

5、重复2,3,4步骤,直到左边指针的值大于右边指针的值停止。

package test.comparable;

public class Quick {

    public static void sort(Comparable[] a){
        sort(a,0,a.length-1);
    }

    private static void sort(Comparable[] a,int lo ,int hi){
        //安全性校验
        if(hi<=lo){
            return;
        }
        //需要对数组中lo索引到hi索引之间的元素进行排序
       int partition = partition(a,lo,hi);
        //让左子组有序,

       sort(a,lo,partition-1);

        // 让右子组有序

        sort(a,partition+1,hi);
    }
    //对数组a中,从索引lo到索引hi之间的元素进行分组,并返回分组界限对应的索引
    private static int partition(Comparable[] a , int lo , int hi ){
        //确定分界值
        Comparable key = a[lo];
        //定义俩个指针,分别指向待切分元素的最小索引处和最大索引处的下一个位置
        int left=lo;
        int right=hi+1;
        //切分
        while(true){
            //先从右往左扫描,移动right指针,找到一个比分界值小的元素,停止
            while(less(key,a[--right])){
                if(right==lo){
                    break;
                }
            }
            //再先从左往右扫描,移动left指针,找到一个比分界值大的元素,停止
            while(less(a[++left],key)){
                if(left==hi){
                    break;
                }
            }

            //判断left>=right,如果是,则证明元素扫描完毕,如果不是,则交换元素
            if(left>=right){
                break;
            }else{
                exch(a,left,right);

            }
        }
        exch(a,lo,right);
        return right;

    }

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

    /**
     * 数组元素i和j交换位置
     * @param a
     * @param i
     * @param j
     */
    private static  void exch(Comparable<?>[]a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值