排序算法学习笔记(sorting algorithms)

写在笔记前面的话:笔记中用到的一些方法是算法第四版提供的stdlib.jar里的,大家可以点这里去官网下载
如果发生导入jar包后无法引用的情况,参考网页最下面的 Q&A 点击下载stdlib-package.jar再导入就行了

排序算法模板(template for sorting algorithms)

  之前写排序算法时,比较,交换等步骤都写在一起,每个算法里面都要单独写一遍比较,交换,今天看了算法第四版,它的排序类算法都极其简洁,将比较,交换,判断是否有序,打印都单独写成方法以供调用,看过之后收益颇丰,现将模板整理如下。
//比较
Public static boolean less(Comparable c1, Comparable c2){
    return c1.compareTo(c2) < 0;
}

//交换
Public static void exec(Comparable[] c,int I, int j){
    Comparable c1 = c[i];
    c[i] = c[j];
    c[j] = c1;
}

//判断是否有序
Public static boolean isSorted(Comparable[] c){
    for(int I = 0; I < c.length; i++){
        if(less(c[i+1],c[i])) return false;
}
return true;
}

//单行中打印数组
Public static void show(Comparable[] c){
    for(int I = 0; I < c.length; i++)
        // StdOut是算法第四版中集成的打印类,也可以自己换成普通的打印方法
        StdOut.print(a[i] + “”);
StdOu.println();
}

//main方法
Public static void main(String[] args){
    得到初始数组c;
    sort(c);
    //若无序则中断程序,没搞明白为什么要加上这个
    assert isSorted(c);
    show(c);
}

初级排序算法之选择排序

选择排序的原理

顾名思义,即每次将一个最小值选择出来放在前面。
比如将数组【1,4,2,3,7,5】排序
step1:从第一个坑开始遍历数组,选出最小值1,放在第一个坑里面
step2:从第二个坑开始遍历数组,选出最小值2,放在第二个坑里面
.
.
.
step5:从第五个坑开始遍历数组,选出最小值5,放在第五个坑里面

算法的实现

现将代码整理如下

    Selection 类
    ```
    package sort;


    /*
     * 选择排序,每次循环选出最小值,将其依次插入
     */
    public class Selection {

        public static void sort(Comparable[] c) {

            SortBasicClass sbc = new SortBasicClass();
            for (int i = 0; i < c.length -1; i++) {
                int min = i;
                for (int j = i + 1; j < c.length; j++) {
                    //less方法,比较
                    if (sbc.less(c[j], c[min])) {
                        min = j;
                    }
                }
                //exec方法,交换
                sbc.exec(c, i, min);
            }
        }
    }

    ```

    SortBasicClass类(前面所说的模板类,实现了比较,交换等必用的功能)

    ```
    package sort;

    import edu.princeton.cs.introcs.StdOut;

    public class SortBasicClass {

        // less方法,比较
        public static boolean less(Comparable c1, Comparable c2) {

            return c1.compareTo(c2) < 0;
        }

        // exec方法,交换
        public static void exec(Comparable[] c, int i, int j) {

            Comparable c1 = c[i];
            c[i] = c[j];
            c[j] = c1;
        }

        // isSorted方法,检查是否有序,若否则终止程序
        public static boolean isSorted(Comparable[] c) {

            for (int i = 0; i < c.length; i++) {
                for (int j = i + 1; j < c.length; j++) {
                    if (less(c[j], c[i]))
                        return false;
                }
            }
            return true;
        }

        // show方法,打印有序集合
        public static void show(Comparable[] c) {
            for (int i = 0; i < c.length; i++)
                StdOut.print(c[i] + ",");
            StdOut.println();
        }
    }

    ```
    SortTestClass类(测试类,main方法)


    ```
            package sort;

    import java.util.Random;
    import java.util.Scanner;

    import edu.princeton.cs.introcs.StdRandom;

    public class SortTestClass {

        public static void main(String args[]) {

            SelectionTest();
        }

        // 选择排序的测试,这里需要从控制台输入待排数据
        public static void SelectionTest() {

            System.out.println("please input...");
            Scanner sc = new Scanner(System.in);
            char[] ch = sc.nextLine().toCharArray();
            Comparable[] c = new Comparable[ch.length];
            for (int i = 0; i < ch.length; i++) {
                c[i] = ch[i];
            }
            Selection.sort(c);
            assert SortBasicClass.isSorted(c);
            SortBasicClass.show(c);
        }
    }

    ```

初级排序算法之插入排序

插入排序的原理

将数组分为有序和无序两个部分,依次将无序部分的元素插入有序部分合适的位置中去。
同样以数组【1,4,2,3,7,5】为例
step1:有序部分无序部分以 ‘/’ 分割【1 / 4,2,3,7,5】,无序部分第一个元素是4,将4放在有序部分合适的位置即1的后面,排序后数组为 【1,4,2,3,7,5】
step2:有序部分无序部分以 ‘/’ 分割【1, 4 / 2,3,7,5】,无序部分第一个元素是2,将2放在有序部分合适的位置即1和4之间,排序后数组为 【1,2,4,3,7,5】
.
.
.
step6:有序部分无序部分以 ‘/’ 分割【1, 2,3,4 , 7 / 5】,无序部分第一个元素是5,将5放在有序部分合适的位置即3和7之间,排序后数组为 【1,2,4,3,5,7】

算法的实现

Insertion类

    ```
    package sort;

    /*
     * 插入排序,依次将数插入合理的位置
     */
    public class Insertion {

        public static void sort(Comparable[] c){

            for (int i = 0; i < c.length; i++) {
                for (int j = i; j >0 && SortBasicClass.less(c[j], c[j-1]); j--) 
                    SortBasicClass.exec(c, j, j-1);
            }
        }
    }

    ```

测试类同上选择排序,代码如下

    ```
    package sort;

    import java.util.Random;
    import java.util.Scanner;

    import edu.princeton.cs.introcs.StdRandom;

    public class SortTestClass {

        public static void main(String args[]) {

            InsertionTest();

        }

        // 插入排序的测试
            public static void InsertionTest() {

                Comparable[] c = new Comparable[100];
                for (int i = 0; i < 100; i++) {
                    c[i] = StdRandom.uniform(1, 100);
    //              c[i] = Math.random();
                }
                Insertion.sort(c);
                assert SortBasicClass.isSorted(c);
                SortBasicClass.show(c);
            }
    }

    ```

排序算法性能比较(Sort Compare)

在研究排序算法的性能时,可以写一个实验用例来做实验。
下面是我参照算法第四版SortCompare类写的一个方法,可以自行调整N,T的大小多次验证,我的计算机中选择排序的速度大概是插入排序的1.7倍。具体的排序算法可以根据上面的模板自行写出。

SortCompare类代码:

```
package sort;

import edu.princeton.cs.introcs.StdOut;
import edu.princeton.cs.introcs.StdRandom;
import edu.princeton.cs.introcs.Stopwatch;

//各种排序算法的比较
public class SortCompare {

    public static void main(String [] args){

        double SelectionTime = TimeRandomInput("Selection",100,20000);
        double InsertionTime = TimeRandomInput("Insertion",100,20000);

        StdOut.println("Selection costs " + SelectionTime + " seconds");
        StdOut.println("Selection costs " + InsertionTime + " seconds");
        StdOut.printf("Selection divided by Insertion is %.2f", SelectionTime/InsertionTime);
    }

    //排序以及其花费的时间
    public static double time(String alg,Double[] d){

        Stopwatch timer = new Stopwatch();

        if(alg.equals("Selection")) Selection.sort(d);
        if(alg.equals("Insertion")) Insertion.sort(d);

        return timer.elapsedTime();
    }

    //生成随机数组,并调用排序算法
    public static double TimeRandomInput(String alg,int N,int T){

        double total = 0.0;
        Double[] d = new Double[N];
        for (int i = 0; i < T; i++) {

            for (int j = 0; j < d.length; j++) {

                d[j] = StdRandom.uniform();
            }

            total += time(alg,d);
        }


        return total;
    }
}





```

你可能感兴趣的:(算法-第四版,排序算法分析)