常见的算法排序

        无论是开发还是架构,是java还是人工智能,算法都是基础。每种算法的关键点,与其他算法的区别联系,都要宏观理解掌握。计算机算法排序包括内排序(内存)和外排序(磁盘IO),下文主要针对内排序,对比分析。

        不同的排序算法有着不同的时间开销和空间开销,比如常用的快速排序和插入排序,需要对序列中的数据进行比较,这样的统称为“基于比较的排序”,它的时间下限是不能超越 O(NlogN)的,证明略。对应的有时空权衡的“非基于比较的排序”:桶排序、基数排序等,它可以突破O(NlogN)时间下限,但注意的是,分配排序的使用是有条件限制的,例如桶排序是受元素大小限制,和元素分布限制等。在特定场合下,非基于比较的排序的运算速度很快。

常见的算法排序_第1张图片

 

直接选择排序—蛮力法

    思想:假设选择的第一个是最小值,作为有序数组。依次和后边的元素比较,如果后边的比假设最小的还小,那就交换,每次都能选出最小的。核心特点是假设最小值,记录下标索引。

    时间复杂度:O(n²)

public static void simpleSelect(int[] a){
    for (int i =0; i

直接插入排序—减治法

    思想:每次插入都与邻近记录逐个比较,直到找到第一个不大于新纪录的值停止。所以它是稳定的,遇到值相等的,插入排序仍然会维持原始顺序,直到排序结束二者的相对顺序也没有改变。特点是短数据、基本有序。

    时间复杂度:O(n²)

public static void sort(int[] arr){
    for (int i=1; i=0&&temp

冒泡排序--蛮力法

    思想:两两比较,如果逆,交换,直至最大or最小。

    时间复杂度:O(n²)

private static  void sort(int[] a){
    for (int i=0; i  a[j+1]){
                int temp  = a[j];
                a[j] = a[j+1];
                a[j+1] =temp;
            }
        }
        System.out.println("第"+i+"遍:"+ Arrays.toString(a));
    }
}

堆排序--变治法 --直接选择排序的升级版

    思想:构建堆(最大堆/最小堆),减少重复的比较。

    时间复杂度:O( nlogn)

public class HeapSort {

    public static void sort(int[] a){
        for (int i =a.length/2-1; i>=0; i--){
            adjustHeap(a,i,a.length);
        }

        for (int j=a.length-1; j>0; j--){
            swap(a,0,j);
            adjustHeap(a,0,j);
        }
    }

    public static void adjustHeap(int[] a, int i, int length){
        for (int k = 2*i+1; k a[i]){
                a[i] =a[k];
                a[k] = temp;
                i =k;
            }else {
                break;
            }
            System.out.println( Arrays.toString(a));
        }
    }

    public static void swap(int[] a, int root, int last){
        int temp = a[root];
        a[root] = a[last];
        a[last] =temp;
    }
    public static void main(String[] args) {
        int[] arr ={4,6,8,5,9};
        System.out.println("原数据:"+Arrays.toString(arr));
        sort(arr);
    }
}

希尔排序—变治+分治+减治法 --插入排序的升级版

    思想:分组版的插入排序,类似折半方法,先分组排序,使数据基本有序。

    时间复杂度:接近 O( nlogn)

public class ShellSort {
    public static void sort(int[] arr) {
        int len = arr.length;
        int gap;//步长
        int istIndex;//插入位置索引
        int tmp;
        System.out.println("原始顺序: "+ Arrays.toString(arr));
        //按照步长来分组
        for(gap = len / 2; gap >= 1; gap /= 2) {
            //类似插入排序的方法
            for (int i = gap; i < len; i++) {
                tmp = arr[i];//取出暂存
                istIndex = i;//插入的位置
                while ((istIndex > (gap-1) && tmp < arr[istIndex - gap])) {
                    //插入位置往前移,寻找合适位置
                    arr[istIndex] = arr[istIndex - gap];
                    istIndex -= gap;
                }
                arr[istIndex] = tmp;
            }
            System.out.println("步长为"+gap+"的排序: "+ Arrays.toString(arr));
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[10];
        //初始化数组
        for (int i = 0; i < 10; i++) {
            arr[i] = (int) (Math.random() * (100 + 1));
        }
        ShellSort.sort(arr);
    }
}

快速排序--分治法 --冒泡排序的升级版

    思想:二分折半的思想,找出基准值 (start+end)/2;L从左边找比基准值大的数,R从右边找比基准值小的数,然后交换,直到L和R相遇。

    时间复杂度:O( nlogn) 尤其是数据量大的时候,更明显。

public class QuickSort {
    public static void sort(int[] arr,int low, int hith){
        int i = low;
        int j = hith;
        int key = arr[low];

        if (i>=j){
            return;
        }

        while (ikey){
                j--;
            }
            while (i

归并排序--分治法

    思想:分而治之,将问题分为子问题递归求解,再“治”合并子问题。是稳定的排序算法。

    时间复杂度:O( nlogn) 仅次于快速排序

public class MergeSort {
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        sort(arr,0,arr.length-1,temp);
    }
    private static void sort(int[] arr,int left,int right,int []temp){
        if(left

关于算法是否稳定,可以总结为是否是相邻比较,如果都是相邻比较,那肯定是稳定的排序算法;如果有不相邻之间的比较,那就是不稳定的排序算法,因为不相邻的比较,会打乱原序列相同数据的相对有序性。

桶排序和计数排序,很多资料表明二者是一种排序,都是对号入座。至于说是否稳定,得看实现方法。我知道的有2种实现方法,一种是稳定的,一种是不稳定。参考这篇文章《计数排序、桶排序》,文章里说的计数排序,就是稳定的排序,它的排序结果是从初始序列的尾部开始往前扫描,以保证算法的稳定性。而文章里的桶排序,是直接顺序地扫描数组C(此时C[i]可以表示A中值为i的元素的个数),就可以求出排序后的结果,所以它不能求出稳定的order,不稳定。

常见的算法排序_第2张图片

你可能感兴趣的:(步步人工智能)