常见的排序算法

1.二分查找算法

    public int search(int[] args, int num) {
        int start = 0;
        int end = args.length - 1;
        while (start <= end) {
            int mid = start + (end-start) / 2;
            if (num < args[mid]) {
                end = mid - 1;
            }
            if (num > args[mid]) {
                start = mid + 1;
            }
            if (num == args[mid]) {
                return mid;
            }
        }
        return -1;
    }

2.常见的排序算法          如果相同元素的相对次序不发生改变,那这种排序方式是稳定的排序方式 

           堆排序、快速排序、希尔排序、直接选择排序是不稳定的排序算法,而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。

  2.1.冒泡排序:时间复杂度为:O(n2) ,

    原理:依次比较两个相邻的元素,将值大的元素交换到后面;这样每一趟就把最大的值放在了最后,然后下一趟对剩余的元素进行比较,直到数组有序;

              算法分析:N个数字要排序完成,总共进行N-1趟排序,每i趟的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数

    

    public static void sort(int[] args) {
        int temp = 0;
        // 标记每趟是否发生变化
        boolean flag = false;
        for (int i = 0; i < args.length - 1; i++) {
            // 注意这里,下边要进行加1,为防止数组越界要减1
            for (int j = 0; j < args.length - i - 1; j++) {
                // 如果前面的数比后面的数大,则进行交换
                if (args[j] > args[j + 1]) {
                    temp = args[j];
                    args[j] = args[j + 1];
                    args[j + 1] = temp;
                    flag = true;
                }
            }
            if (!flag) {
                return;
            }
        }
    }

  2.2.直接选择排序    时间复杂度为:O(n2

    算法思想:首先在未排序的数列中找到最小(or最大)元素,然后将其存放到数列的起始位置;接着,再从剩余未排序的元素中继续寻找最小(or最大)元素,然后放到已排序序列的末尾。以此类推,直到                                   所有元素均排序完毕。

    public static void sort(int[] arg) {
        for (int i = 0; i < arg.length - 1; i++) {
            // 假定每趟开始的最小元素为未排序的第一个元素
            int minIndex = i;
            for (int j = i + 1; j < arg.length; j++) {
                // 如果存在元素比当前最小元素要小;
                if (arg[minIndex] > arg[j]) {
                    minIndex = j;
                }
            }
            if (minIndex != i) {
                int temp = arg[i];
                arg[i] = arg[minIndex];
                arg[minIndex] = temp;
            }
        }
    }

  2.3.插入排序   时间复杂度为:O(n2

    算法思想:将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,                                 n个元素需要进行n-1趟排序。

    public static void sort(int[] arg) {

        for (int i = 0; i < arg.length; i++) {

            if (arg[i] < arg[i - 1]) {
                int j;
                // 待插入的数
                int current = arg[i];
                // 从有序表中的最后一个元素开始进行比较
                // current < arr[j],说明待插入元素小于有序表中的j元素,
                // 就需要将arr[j]元素后移;
                for (j = i - 1; j >= 0 && current < arg[j]; j--) {
                    arg[j + 1] = arg[j];
                }
                arg[j + 1] = current;
            }
        }
    }

  2.4.希尔排序    时间复杂度为:O(nlogn)

    算法思想:对于n个待排序的数列,取一个小于n的整数gap=n/2(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入                                  排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap=gap/2的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。

    public static void sort(int[] arg) {
        System.out.println(Arrays.toString(arg));
        for (int step = arg.length / 2; step > 0; step = step / 2) {
            // 每组进行直接插入排序
            for (int i = step; i < arg.length; i++) {
                int current = arg[i];
                int j;
                for (j = i - step; j >= 0 && current < arg[j]; j -= step) {
                    arg[j + step] = arg[j];
                }
                arg[j + step] = current;
            }
            // 一次分组后的排序结果
            System.out.println(Arrays.toString(arg));
        }
    }

  2.5.快速排序   时间复杂度O(nlogn)

    算法思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归                                    进 行,以此达到整个数据变成有序序列。

    public static void sort(int[] arg, int left, int right) {
        System.out.println(Arrays.toString(arg));
        System.out.println("left=" + left + ", right=" + right);
        int lt = left;
        int rt = right;
        // pivot 是中轴值
        int pivot = arg[(left + right) / 2];
        // 循环让比pivot小的值放在左边,比pivot大的值放在右边
        while (lt < rt) {
            // 在pivot的左边一直找,直到找到一个比pivot大的值
            while (arg[lt] < pivot) {
                lt++;
            }
            // 在pivot的右边边一直找,直到找到一个比pivot小的值
            while (arg[rt] > pivot) {
                rt--;
            }
            // 表示pivot的左边已经是全部小于等于pivot;pivot的右边已经是大于等于pivot
            if (lt >= rt) {
                break;
            }
            // 左右两边进行交换
            int temp = arg[lt];
            arg[lt] = arg[rt];
            arg[rt] = temp;

            // 交换完成后如果发现lt处的值等于pivot,则rt减1;
            if (arg[lt] == pivot) {
                rt--;
            }
            // 交换完成后如果发现rt处的值等于pivot,则lt加1;
            if (arg[rt] == pivot) {
                lt++;
            }
        }

        // 如果lt==rt,则必须进行加减;
        if (lt == rt) {
            lt++;
            rt--;
        }
        if (left < rt) {
            sort(arg, left, rt);

        }
        if (right > lt) {
            sort(arg, lt, right);
        }
    }

 

posted @ 2020-08-14 16:31  剧毒术士  阅读(165)  评论(0编辑  收藏  举报