排序算法--------交换排序(冒泡排序和快速排序)

排序算法------交换排序(冒泡排序和快速排序)

目录

排序算法------交换排序(冒泡排序和快速排序)

1、冒泡排序

2、快速排序


1、冒泡排序

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

1.1 算法思路

       (1)第一次比较:首先比较第一和第二个数,将小数放在前面,将大数放在后面。

    (2)比较第2和第3个数,将小数 放在前面,大数放在后面。

    (3)如此继续,知道比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成

    (4)针对所有的元素重复以上的步骤,除了最后一个,依次类推,每一趟比较次数减少依次。

1.2 算法动态图

1.3 算法分析

1.如果我们的数据正序,只需要走一趟即可完成排序。冒泡排序最好的时间复杂度为O(n)。

2.如果很不幸我们的数据是反序的,则需要进行n-1趟排序,这时最坏时间需要O(n2)。

算法 最好时间 最坏时间 平均时间 额外空间 稳定性
冒泡算法 O(n) O(n2) O(n2) 1 稳定

  关于稳定性:因为在比较的过程中,当两个相同大小的元素相邻,只比较大或者小,所以相等的时候是不会交换位置的。而当两个相等元素离着比较远的时候,也只是会把他们交换到相邻的位置。他们的位置前后关系不会发生任何变化,所以算法是稳定的。

1.4 算法实现


/**
 * 冒泡算法
 */
public class BubbleSort {
    public int[] sort(int[] nums){
        if(nums == null || nums.length == 0){ //若数组为空,直接返回null
            return null;
        }
        for(int i = 0; i < nums.length; ++i){
            for(int j = 0; j < nums.length - i - 1; ++j){
                if(nums[j] > nums[j + 1]){  //依次比较两个相邻的数的大小
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                }
            }
        }
        return nums;
    }
    public static void main(String args[]){
        int[] nums = new int[]{5,69,54,21,5,36,7,84};
        BubbleSort bubbleSort = new BubbleSort();
        nums = bubbleSort.sort(nums);
        for(int num : nums) {
            System.out.print(num + "    ");
        }
    }
}

    运行结果:5    5    7    21    36    54    69    84 

1.5 优化

参考链接https://www.cnblogs.com/jyroy/p/11248691.html

(1)当数组是,5,4,3,1,2 的时候的时候就非常明显了,实际上在第一次循环的时候整个数组就已经完成排序,但是常规版的算法仍然会继续后面的流程,这就是多余的了。

  为了解决这个问题,我们可以设置一个标志位,用来表示当前第 i 趟是否有交换,如果有则要进行 i+1 趟,如果没有,则说明当前数组已经完成排序

(2)除了上面这个问题,在冒泡排序中还有一个问题存在,就是第 i 趟排的第 i 小或者大的元素已经在第 i 位上了,甚至可能第 i-1 位也已经归位了,那么在内层循环的时候,有这种情况出现就会导致多余的比较出现。例如:6,4,7,5,1,3,2,当我们进行第一次排序的时候,结果为6,7,5,4,3,2,1,实际上后面有很多次交换比较都是多余的,因为没有产生交换操作。

针对上述的问题,我们可以想到,利用一个标志位,记录一下当前第 i 趟所交换的最后一个位置的下标,在进行第 i+1 趟的时候,只需要内循环到这个下标的位置就可以了,因为后面位置上的元素在上一趟中没有换位,这一次也不可能会换位置了。


 

2、快速排序

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

2.1 算法思路

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

     (1)从数列中挑出一个元素,称为 “基准”(pivot);

     (2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

     (3)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

2.2 算法动态图

2.3 算法分析

2.4 算法实现

/**
 * 快速排序
 */
public class QuickSort {
    public void sort(int[] nums , int start , int end){
        int temp;
        int i = start;
        int j = end;
        if(i < j){
            temp = nums[i];
            while (i != j){   
                while (i < j && temp < nums[j]){  //从数组最右边找到第一个比temp小的
                    j--;
                }
                if(i < j){       //交换位置              
                    nums[i] = nums[j];
                    i++;
                }
                while (i < j && temp > nums[i]){ //从数组左边找到第一个比temp大的
                    i++;
                }
                if(i < j){    //交换位置
                    nums[j] = nums[i];
                    j--;
                }
            }
            nums[i] = temp;  
            sort(nums , start , i - 1);  //分别递归排序
            sort(nums , i + 1 , end);
        }
    }
    public static void main(String args[]){
        int[] nums = new int[]{5,69,54,21,5,36,7,84};
        QuickSort quickSort = new QuickSort();
        quickSort.sort(nums , 0 , nums.length - 1);
        for(int num : nums){
            System.out.print(num + "   ");
        }
    }
}

   运行结果:

5   5   7   21   36   54   69   84 

2.5 优化

链接:https://www.jianshu.com/p/671981540727

发布了78 篇原创文章 · 获赞 53 · 访问量 8155

猜你喜欢

转载自blog.csdn.net/qqq3117004957/article/details/104936977