• 排序算法汇总


    稳定性定义:排序前后两个相等的数相对位置不变,则算法稳定。

    稳定性得好处:从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。

    稳定的:

      1.插入排序(O(n*n)):将一个元素插入到已经排好序的列表中

    public void selectionSort(int[] a) {
        if (null ==a || a.length < 2) {
            return;
        }
        for (int i = 1; i < a.length; i++) {
            int temp = a[i]; // 暂存
            int j = i - 1;
            while (j >= 0 && temp < a[j]) {
                a[j+1] = a[j];
                j--;
            }
            a[j+1] = temp;
        }
    }

      2.冒泡排序(O(n*n)):相邻两个元素比较大小进行交换,一趟冒泡后会有一个元素到达最终位置

    public void bubbleSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        boolean flag;
        for (int i = 0; i < a.length - 1; i++) {
            flag = false;
            for (int j = 0; j < a.length - 1 - i; j++) {
                if (a[j] > a[j+1]) {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                    flag = true;
                }
                if (flag == false) {
                    return;
                }
            }
        }
    }

      3.归并排序(nlogn):两个有序序列的合并,方法:分治 + 递归

    public static int[] sort(int[] nums, int low, int high) {
        int mid = (low + high) / 2;
        if (low < high) {
            // 左边
            sort(nums, low, mid);
            // 右边
            sort(nums, mid + 1, high);
            // 左右归并
            merge(nums, low, mid, high);
        }
        return nums;
    }
    
    /**
     * 将数组中low到high位置的数进行排序
     * @param nums 待排序数组
     * @param low 待排的开始位置
     * @param mid 待排中间位置
     * @param high 待排结束位置
     */
    public static void merge(int[] nums, int low, int mid, int high) {
        int[] temp = new int[high - low + 1];
        int i = low;// 左指针
        int j = mid + 1;// 右指针
        int k = 0;
    
        // 把较小的数先移到新数组中
        while (i <= mid && j <= high) {
            if (nums[i] < nums[j]) {
                temp[k++] = nums[i++];
            } else {
                temp[k++] = nums[j++];
            }
        }
    
        // 把左边剩余的数移入数组
        while (i <= mid) {
            temp[k++] = nums[i++];
        }
    
        // 把右边边剩余的数移入数组
        while (j <= high) {
            temp[k++] = nums[j++];
        }
    
        // 把新数组中的数覆盖nums数组
        for (int k2 = 0; k2 < temp.length; k2++) {
            nums[k2 + low] = temp[k2];
        }
    }

    不稳定:

      1.希尔排序(n的1.3次方):按步长进行分组,组内直接插入,缩小增量再次进行此步骤,增量为1时相当于一次直接插入

    public void shellSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        for (int d = a.length/2; d > 0; d/=2) {
            for (int i = d; i < a.length; i++) {
            // 内部直接插入
                int temp = a[i];
                int j = i - d;
                while (j >= 0 && temp < a[j]) {
                    a[j+d] = a[j];
                    j -= d;
                }
                a[j+d] = temp;
            }    
        }
    }

    2.选择排序(n*n):每次从无序序列选择一个最小的与第一个元素交换,再从剩下的里面找最小的和第二个元素交换。。

      

    public void selectSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
    
        for (int i = 0; i < a.length; i++) {
            int k = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[j] < a[k]) {
                    k = j;
                }
            }
            if (k != i) {
                int temp = a[k];
                a[k] = a[i];
                a[i] = temp;
            }
        }
    }

    3.快速排序(nlogn):通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序。

    public void quickSort(int[] a, int low, int high) {
    
        if (low < high) {
            int mid = partition(a, low, high);
            quickSort(a, low, mid - 1);
            quickSort(a, mid + 1, high);
        }
    }
    
    private int partition(int[] a, int low, int high) {
        int pivot = a[low];
    
        while (low < high) {
            while (low < high && a[high] >= pivot) {
                high--;
            }
            a[low] = a[high];
            while (low < high && a[low] <= pivot) {
                low++;
            }
            a[high] = a[low];
        }
        a[low] = pivot;
    
        return low;
    }

    4.堆排序(nlogn):利用堆的特性,建堆,调整堆

    // 堆排序
    public void heapSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        buildMaxHeap(a);
    
        for (int i = a.length - 1; i >= 0; i--) {
            int temp = a[0];
            a[0] = a[i];
            a[i] = temp;
            adjustHeap(a, i, 0);
        }
    }
    
    // 建堆
    private void buildMaxHeap(int[] a) {
        for (int i = a.length/2; i >= 0; i--) {
            adjustHeap(a, a.length, i);
        }
    }
    
    // 调整堆
    private void adjustHeap(int[] a, int size, int parent) {
        int left = 2 * parent + 1;
        int right = 2 * parent + 2;
        int largest = parent;
    
        if (left < size && a[left] > a[largest]) {
            largest = left;
        }
    
        if (right < size && a[right] > a[largest]) {
            largest = right;
        }
    
        if (parent != largest) {
            int temp = a[parent];
            a[parent] = a[largest];
            a[largest] = temp;
            adjustHeap(a, size, largest);
        }
    }

      

  • 相关阅读:
    NDK中使用pthread多线程中自己写的一个BUG
    Android Native crash日志分析
    Android细笔记--DataStorage
    求二叉树第n层节点数
    对YUV数据进行裁剪
    Android XML中引用自定义内部类view的四个why
    Android细笔记--ContentProvider
    Android Log Tag含义
    189-RotaeArray
    二分查找法
  • 原文地址:https://www.cnblogs.com/team42/p/7075478.html
Copyright © 2020-2023  润新知