常用排序算法介绍分析(冒泡,选择,插入,快排...)

排序算法是每个程序员都应该掌握的基本技能,常见的排序算法有冒泡排序,快速排序,插入排序,选择排序,堆排序等。今天就来简单介绍下这几种排序方法。

顾名思义冒泡排序就是相邻的两个数字进行比较,如果前边的值大于后边的值则进行值交换,以此类推遍历数组中的所有数字,每次遍历找出最大值的过程就好像气泡从水底向上冒出,所以叫做冒泡排序。下面给出冒泡排序的实现。

冒泡排序实现

第一种(基础冒泡排序):

public static int[] sort(int[] nums) {
        if (nums != null) {
            int i, j = 0;
            int temp = 0;
            for (i = 0; i < nums.length - 1; i++) {
                for (j = 0; j < nums.length - 1 - i; j++) {
                    if (nums[j] > nums[j + 1]) {
                        temp = nums[j + 1];
                        nums[j + 1] = nums[j];
                        nums[j] = temp;
                    }
                }
            }
        }
        return nums;
    }

第二种:是第一种排序的改进版,加了一个flag,在排序过程中如果发现数组已经排好了顺序就不再进行剩余的遍历比较

//改进版
    public static int[] sort2(int[] nums) {
        if (nums != null) {
            int i, j = 0;
            int temp = 0;
            boolean isSorted = true;//设置flag
            for (i = 0; i < nums.length - 1; i++) {
                isSorted = true;
                for (j = 0; j < nums.length - 1 - i; j++) {
                    if (nums[j] > nums[j + 1]) {
                        temp = nums[j + 1];
                        nums[j + 1] = nums[j];
                        nums[j] = temp;
                        isSorted = false;
                    }
                }
                if (isSorted == true) {
                    break;
                }
            }
        }
        return nums;
    }

第三种:在第二种基础上又进行一些优化,优化的思路是在遍历比较过程中记录下最后交换数值的下标(次下标后的元素都是已经排好顺序的),用该下标更新内外两层for循环的范围,这样做的好处是不再对已经排好序的数值进行比较。

public static int[] sort3(int[] nums) {
        if (nums != null) {
            int i, j = 0;
            int temp = 0;
            int k = 0;
            int flag = nums.length - 1;
            boolean isSorted = true;
            for (i = 0; i < flag; i++) {
                isSorted = true;
                k = flag;
                flag = 0;
                for (j = 0; j < k; j++) {
                    if (nums[j] > nums[j + 1]) {
                        temp = nums[j + 1];
                        nums[j + 1] = nums[j];
                        nums[j] = temp;
                        flag = j;
                        isSorted = false;
                    }
                }
                if (isSorted == true) {
                    break;
                }
            }
        }
        return nums;
    }

时间复杂度:若数组是排好序的,一趟扫描即可完成排序,所以冒泡最好的时间复杂度是O(n)。若顺序是相反的,则时间复杂度是O(n*n).所以冒泡的平均时间复杂度是O(n*n)。冒泡排序是一种稳定排序算法,即相同元素的前后顺序没有发生改变。

选择排序实现

选择排序与冒泡排序类似,也是两两比较,只是在比较过程中不对值进行交换,只记录下较小值的下标,在一轮循环结束后可以找到最小值的下标,然后交换默认最小值下标和最小值下标的值,在n轮循环结束后即可完成排序

private static void sort(int[] a) {
        // TODO Auto-generated method stub
        int minIndex = 0;
        int temp = 0;
        boolean isSorted = true;
        for (int i = 0; i < a.length - 1; i++) {
            minIndex = i;
            for (int j = i + 1; j < a.length; j++) {
                if(a[minIndex] > a[j]) {
                    minIndex = j;
                }
            }
            temp = a[minIndex];
            a[minIndex] = a[i];
            a[i] = temp;
        }
    }

选择排序时间复杂度是和冒泡排序一样也是O(n*n),选择排序属于不稳定排序。举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法

猜你喜欢

转载自blog.csdn.net/u011821510/article/details/85723119