冒泡排序,快速排序,归并排序

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
冒泡排序总的平均时间复杂度为 
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法
 
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
 
快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。 
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
 
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
 
代码如下
 
package pro;

import java.util.Arrays;

//冒泡排序, 快速排序, 归并排序
public class SortWay {

    //冒泡
    /*
    冒泡排序算法的原理如下: [1]
    比较相邻的元素。如果第一个比第二个大,就交换他们两个。 [1]
    对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 [1]
    针对所有的元素重复以上的步骤,除了最后一个。 [1]
    持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
     */
    private static void bubbleSort(int[] arr) {
        int n = arr.length;

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

        System.out.println(Arrays.toString(arr));
    }

    /*
    基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,
    其中一部分的所有数据都比另外一部分的所有数据都要小,然后
    再按此方法对这两部分数据分别进行快速排序,整个排序过程可
    以递归进行,以此达到整个数据变成有序序列
     */
    private static void quickSort(int[] arr) {
        int n = arr.length;
        qSort(arr, 0 , n-1);
        System.out.println(Arrays.toString(arr));
    }

    private static int[] qSort(int[] part, int s, int e) {
        int point = part[s];
        int i = s, j = e;

        // 如果开始小于结束,继续寻找替换
        while (i < j) {
            while (i < j && part[j] > point) { // 如果后面的元素大于基准元素。结束点j向前进一
                j--;
            }
            while (i < j && part[i] < point) { // 如果前面的元素小于基准元素。开始点i向后进一
                i++;
            }
            if(part[i] == part[j] && i < j) { // 如果开始元素等于结束元素 开始点i向后进一
                i++;
            } else {        // 交换数值。当结束元素小于基准点 或者 开始元素大于基准点。进行交换位置
                int temp = part[i];
                part[i] = part[j];
                part[j] = temp;
            }
        }
        // 直到找到基准元素前面全部是比它小的,后面是比它大的就可以进行两侧递归排序了。
        if(i-1 > s) part = qSort(part, s , i-1);
        if(j+1 < e) part = qSort(part, j+1 , e);
        return part;
    }

    /*
        归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,
        该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已
        有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子
        序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。+
        速度仅次于快速排序
     */
    private static void mergeSort(int[] arr) {
        int n = arr.length;
        mergeSort(arr, 0 , n-1);
        System.out.println(Arrays.toString(arr));
    }

    private static int[] mergeSort(int[] nums, int l, int r) {
        if(l == r) return new int[]{nums[l]};// 只有一个元素的子序列

        int mid = l + (r-l) / 2;
        //左有序数组
        int[] leftArr = mergeSort(nums, l, mid);
        //右有序数组
        int[] rightArr = mergeSort(nums, mid+1, r);
        //新有序数组
        int[] retArr = new int[leftArr.length+rightArr.length];
        int m = 0, i = 0, j = 0;
        // 将左右两个数组的元素逐一对比合并一个有序的新数组
        while (i < leftArr.length && j < rightArr.length) { // i/j都满足的
            retArr[m++] = leftArr[i] < rightArr[j] ? leftArr[i++] : rightArr[j++];
        }
        //当一个左或者右数组先合并完,再进行单个合并
        while (i < leftArr.length) {
            retArr[m++] = leftArr[i++];
        }
        while (j < rightArr.length) {
            retArr[m++] = rightArr[j++];
        }

        return retArr;
    }

    public static void main(String[] args) {
        int[] arr = {3,5,1,-7,4,9,-6,8,10,4};
        long s = System.nanoTime();
//        bubbleSort(arr);
//        quickSort(arr);
//        mergeSort(arr);
        long e = System.nanoTime();
        System.out.println(e-s);
    }
}

 

 

 

划重点~~~~~~~~~~~

 

简单桶排序

通过开一个数组book[MAX], 对于每个数据出现的次数对其加一book[v]++;

最后按照max进行展开输出就可以了,效率是n,但是对于稀疏图比较浪费空间。

 

冒泡排序核心部分

fori(int i = 1; i <= n-1; i++) // n个数进行排序,只用n-1趟就可以。

  fori(j=1; j <= n-i; j++) // 从第一位开始比较到最后一个尚未归为的数,想想为什么到n-i 就可以了  而不需要到n-1, 因为每次排序都会确定一个数已经被排好序了 。

 

 

 

 

posted @ 2020-11-02 16:20  姓蜀名黍  阅读(291)  评论(0)    收藏  举报