交换排序(冒泡、快排、java)

一.概念

两两比较,发生逆序则交换

二.冒泡排序

    public static void main(String[] args) {
        int arr[] = new int[]{1, 8, 6, 9, 9, 4, 7, 3, 8, 9, 3, 2, 7};
        int n=arr.length;//n个数
        int m; //m趟
        for (m = 0; m < n - 1; m++) {
            //比较n-m次,n-m-1因为arr[j+1]会使用最后一个元素
            for (int j = 0; j < n - m- 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int x = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = x;
                }
            }
        }
        for (int k = 0; k < arr.length; k++) {
            System.out.print(arr[k] + "\t");
        }
    }

public static void main(String[] args) {
        int arr[] = new int[]{1, 8, 6, 9, 9, 4, 7, 3, 8, 9, 3, 2, 7};
        int n=arr.length;//n个数
        int m; //m趟
        int flag=1;//是否有序标志
        for (m = 0; m < n - 1&&flag==1; m++) {
            flag=0;//如果没交换则0
            for (int j = 0; j < arr.length - m- 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int x = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = x;
                    flag=1;//交换则标志
                }
            }
        }
        for (int k = 0; k < arr.length; k++) {
            System.out.print(arr[k] + "\t");
        }
    }

最好情况,数组已经正序,只需要1趟(有flag),比较n-1次,不需要交换。

最坏情况,数组逆序,需要n-1趟,第一趟比较n-1,第二趟n-...

效率比其他O(n^2)算法好

三.快速排序

用到递归,递归结束条件:子表元素只剩一个

privotkey:中心元素

   public static void main(String[] args) {
//        int arr[] = new int[]{0, 1, 8, 6, 9, 9, 4, 7, 3, 8, 9, 3, 2, 7};
        int[] arr = new int[]{0, 9, 7, 8, 6, 5, 4, 3, 2, 1};
        sort(arr, 1, arr.length - 1);
        for (int i = 1; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }

    private static void sort(int[] arr, int low, int high) {
        if (arr.length == 1) {
            return;
        }
        int part = part(arr, low, high);
        if (low < part)  //low<part 元素不止一个才有排序意义
            sort(arr, low, part);
        if (high > part + 1)
            sort(arr, part + 1, high);
    }


    //找到中间值的位置,将其分成两个数组,左边比中间值小或相等,右边比中间值小或相等
    private static int part(int[] arr, int low, int high) {
//        System.out.print("low="+low);
        arr[0] = arr[low]; //将数组第一个元素作为 中间值,移动到哨兵;
        // 用了第一个元素做中间值,假设最终位置是9,在遍历到5时,5左的位置已经是全部小于哨兵了

        while (low < high) {
            //从后往前,找一个<哨兵的值,移动到 low位置   !!!注意相等的值不移动
            while (low < high && arr[0] <= arr[high]) {
                high--;
            }
            //找到high是比哨兵小的位置, 把high元素移动到左边后,high处认为空
            //如果遍历一遍没有找到,则high 必定和 low相同,赋值下也没关系;同时证明右边都比哨兵大,此时 high low相同,不会再继续执行,且找到了中间值位置达成目的
            arr[low] = arr[high];

            //high处为空,从前往后,找比哨兵大的位置  !!!注意相等的值不移动
            while (low < high && arr[0] >= arr[low]) {
                low++;
            }
            //找到low是比哨兵大的元素,移动到右边后, low处认为空元素
            //如果遍历一遍没有找到,则high 必定和 low相同,赋值下也没关系
            arr[high] = arr[low];
        }
        //经过上个循环,分成了左右两数组
        //将中间值放在low,low
        arr[low] = arr[0];
        return low;
    }

 part方法时间复杂度O(n);

sort方法执行part,假设数组长度n,每个子表长度为1时不再执行part,n/2/2/2...=1   n/ (x^2)=1    n=x^2  x=logn

需要O(logn)的栈空间

数组本身有序,则退化成冒泡排序

数组越乱越好,如果基本有序,则需要改变选取划分元素的方法,比如选取中间位置的元素,而非第一个元素,不过即便最坏情况也有O(n2),不会太差。

四.参考直接插入排序,设计一个交换排序

直接插入排序,是将待排序的数字 插入到已经排好序的序列。

我们可以将待排序的数字 交换到已经排好序的序列合适位置。

    public static void main(String[] args) {
        int arr[] = new int[]{1, 8, 6, 9, 9, 4, 7, 3, 8, 9, 3, 2, 7};

        for (int i = 0; i < arr.length; i++) {
            for (int j = i; j > 0; j--) {
                if (arr[j] < arr[j - 1]) {
                    int x = arr[j];
                    arr[j] = arr[j - 1];
                    arr[j - 1] = x;
                }
            }
        }

        for (int k = 0; k < arr.length; k++) {
            System.out.print(arr[k] + "\t");
        }
    }

猜你喜欢

转载自blog.csdn.net/u014203449/article/details/113676262
今日推荐