排序

快排

1:基本思想-选择一个基准元素,将比基准元素小的元素放在其前面,比基准元素大的元素放在其后面,然后:再将小于其基准值元素的子数列和大于基准元素的子数列按原来的方法排序。

2:优点-极快,数据移动少。缺点-不稳定(相同值的相对位置有发生改变)。

3:效率分析-此排序算法的效率在序列越乱的时候,效率越高。在数据有序时,会退化成冒泡排序。

4:对于基准的选择-三数(low、mid、high)中取、随机选取基准。

5:优化方法-a.当待排序序列的长度分割到一定大小后,使用插入排序(对于很小和部分有序的数组,快排不如插排好)。b.再一次分割结束后,可以把与key相等的元素聚集在一起,继续下次分割时,不必再对于key相等的元素分割。

6:最坏的时候(O(n2))也就是在随机快速排序的partition过程的时候每次选取标志数的时候都大或者最小值,

/**
 * @author zzm
 * @data 2020/4/12 22:13
 */
public class SortQuick {
    public static void main(String[] args) {
        int[] arr = {16, 7, 3, 20, 17, 8};

        quickSort(arr, 0, arr.length - 1);

        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    private static void quickSort(int[] a, int l, int r) {
        if (l >= r) return;
        int i = l, j = r;
        int key = a[l];
        while (i < j) {
            while (i < j && a[j] >= key) j--;
            if (i < j) a[i++] = a[j];
            while (i < j && a[i] < key) i++;
            if (i < j) a[j--] = a[i];
        }
        a[i] = key;
        quickSort(a, l, i - 1);
        quickSort(a, i + 1, r);
    }


}

 

堆排序

1:二叉堆定义-二叉堆是完全二叉树或近似完全二叉树。满足特性a.父节点的键值总大于或等于(小于或等于)任何一个子节点的键值。b.每个节点的左子树和右子树都是一个二叉堆。

2:堆的存储-一般用数组来表示堆,i结点的父节点下标是(i-1)/2,它的左右节点的下标分别是2*i+1和2*i+2。

3:应用-寻找M个数中前k个最小的数并保持有序。时间复杂度:O(K)[创建K个元素最大堆的时间复杂度] +M-K*log(K)[对剩余M-K个数据进行比较并每次对最大堆进行从新最大堆化]

4:不稳定(相同值的相对位置有发生改变);

5:实现(构建堆,调整堆)

/**
 * @author zzm
 * @data 2020/4/12 21:57
 */
public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {16, 7, 3, 20, 17, 8};

        heapSort(arr);

        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    private static void heapSort(int[] a) {
        int len = a.length;
        for (int i = (len - 1) / 2; i >= 0; i--) adjustHeap(a, i, a.length);

        for (int i = len - 1; i > 0; i--) {
            int temp = a[i];
            a[i] = a[0];
            a[0] = temp;

            adjustHeap(a, 0, i);
        }
    }

    private static void adjustHeap(int[] a, int parent, int len) {
        int temp = a[parent];
        int lChild = 2 * parent + 1;
        while (lChild < len) {
            int rChild = lChild + 1;
            if (rChild < len && a[rChild] > a[lChild]) lChild++;
            if (temp > a[lChild]) break;
            a[parent] = a[lChild];
            parent = lChild;
            lChild = 2 * parent + 1;
        }
        a[parent] = temp;
    }
}

归并排序

1:基本思想-首先将初始序列的n个记录看成n个有序的子序列,每个子序列的长度为1,然后两两合并,得到n/2个长度为2的有序子序列,…以此类推,直到得到一个长度为n的有序序列为止。

2:适用场景-n较大,并且要求排序稳定,则可以选择归并排序。

import java.util.Arrays;

/**
 * @author zzm
 * @data 2020/4/12 22:44
 */
public class SortMerge {
    public static void main(String[] args) {
        int[] arr = {16, 7, 3, 20, 17, 8};

        mergeSort(arr, 0, arr.length - 1);

        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    private static void mergeSort(int[] arr, int l, int r) {
        if (l < r) {
            int mid = (l + r) / 2;
            mergeSort(arr, l, mid);
            mergeSort(arr, mid + 1, r);
            merge(arr, l, r, mid);
        }
    }

    private static void merge(int[] a, int l, int r, int mid) {
        int[] lefts = Arrays.copyOfRange(a, l, mid + 1);
        int[] rights = Arrays.copyOfRange(a, mid + 1, r + 1);

        int i, j, k;
        for (i = 0, j = 0, k = l; i < lefts.length && j < rights.length; k++) {
            if (lefts[i] < rights[j]) a[k] = lefts[i++];
            else a[k] = rights[j++];
        }
        
        if (i < lefts.length) for (; i < lefts.length; i++) a[k++] = lefts[i];
        if (j < rights.length) for (; j < rights.length; j++) a[k++] = rights[j];
    }
}

 

posted @ 2020-04-12 22:13  zzmhust  阅读(160)  评论(0)    收藏  举报