排序问题(1)

排序的几种方法

1.冒泡 选择 插入三种排序方法

/**
 * 描述: 
 * 冒泡、选择、插入三种排序
 */
public class Sort {

    @Test
    public void test01(){
        int[] arr = new int[]{12,5,7,89,54,32,13};
        // 在一个无序的数组中,按顺序搜索数组找元素,时间复杂度:O(n)
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == 54)
            {
                System.out.println("find 54!");
                break;
            }
        }
        insertSort(arr);
        // [5, 7, 12, 13, 32, 54, 89]
        int idx = binarySearch(arr, 0, arr.length-1, 54);
        System.out.println("54 idx:" + idx);
    }
    /**
     * 二分查找的实现,找到val返回其下标,找不到返回-1
     * 时间复杂度:O(log2n) 对数时间
     * @param arr
     * @param first
     * @param last
     * @param val
     * @return
     */
    private int binarySearch(int[] arr, int first,
                             int last, int val) {
        while(first <= last){
                int mid = (first + last)/2;
                if(val < arr[mid]){
                    last = mid-1;
                } else if(val > arr[mid]){
                    first = mid+1;
                } else {
                    return mid;
                }
        }
        return -1;
    }
    public static void main(String[] args) {
        int[] arr = new int[]{12,5,7,89,54,32,13};
        /*int[] arr = new int[10000];
        Random rd = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = rd.nextInt(65535);
        }*/
        long begin, end;

        // 冒泡排序
        
        begin = System.currentTimeMillis();
        //bubbleSort(arr);
        end = System.currentTimeMillis();
        System.out.println("bubbleSort:" + (end-begin) + "ms");

        // 选择排序

        begin = System.currentTimeMillis();
        //choiceSort(arr);
        end = System.currentTimeMillis();
        System.out.println("choiceSort:" + (end-begin) + "ms");
        //System.out.println(Arrays.toString(arr));

        // 插入排序
        
        begin = System.currentTimeMillis();
        insertSort(arr);
        end = System.currentTimeMillis();
        System.out.println("insertSort:" + (end-begin) + "ms");
        System.out.println(Arrays.toString(arr));
    }
    /**
     * 插入排序的思想
     * 4 8 12 67 90
     *                    k
     *           20 32 41 28
     *            j       i
     * 插入排序的优化
     * @param arr
     */
    private static void insertSort(int[] arr) {
        // 12 12 7 8 9
        for(int i=1; i<arr.length; ++i) {
            int val = arr[i];
            // 优化成二分查找合适的插入位置,不再使用线性查找
            // 0  j  找第一个小于val的值
            int index = findInsertPos(arr, 0, i-1, val);
            for(int j=i; j>index; --j){
                arr[j] = arr[j-1];
            }
            arr[index] = val;
            /*
            // 在i前面已经排序好的序列中,找i元素插入的合适的位置
            int j=i-1;
            for(; j>=0; --j){
                if(val < arr[j]) {
                    arr[j+1] = arr[j];
                }
                else {
                    break;
                }
            }
            // 把val元素插入到当前位置,然后循环结束
            arr[j+1] = val;
            */
        }
    }
    private static int findInsertPos(
            int[] arr, int i, int j, int val) {
        while(i <= j)
        {
            int mid = (i+j)/2;
            if(val < arr[mid])
            {
                j = mid-1;
            } else {
                i = mid+1;
            }
        }
        return i;
    }
    /**
     * 选择排序
     * 12 4 67 8 90 32 41 46
     * 1. 当前元素和后面元素比较,找出最小值
     * 2.
     * 不稳定
     * 2 3 5 5
     * @param arr
     */
    private static void choiceSort(int[] arr) {
        for(int i=0; i<arr.length-1; ++i)
        {
            int min = arr[i];
            int k = i;
            for(int j=i+1; j<arr.length; ++j)
            {
                if(min > arr[j]){
                    min = arr[j];
                    k = j;
                }
            }
            // 0 k
            if(k != i)
            {
                int tmp = arr[i];
                arr[i] = arr[k];
                arr[k] = tmp;
            }
        }
    }
    /**
     * 冒泡排序
     * 排序算法的两个问题:
     * 1.时间复杂度:O(n^2)  空间复杂度:O(1)
     * 2.稳定性:稳定
     * @param arr
     */
    private static void bubbleSort(int[] arr) {
        for(int i=0; i<arr.length-1; ++i){
            boolean swap = false;
            for(int j=0; j< arr.length-1-i; ++j){
                if(arr[j] > arr[j+1]){
                    swap = true;
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
            if(!swap){
                return;
            }
        }
    }
}

2.堆排

/**
 * 描述: 堆排序
 */
public class HeapSort {

    public static void main(String[] args) {
        int[] arr = new int[10];
        Random rd = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = rd.nextInt(100);
        }

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

    /**
     * 实现堆排序
     * @param arr
     */
    private static void heapSort(int[] arr) {
        int n = arr.length-1;

        // 从第一个非叶子节点开始,把大值往父节点调整
        for(int i=(n-1)/2; i>=0; --i){
            adjust(arr, i, arr.length);
        }

        for(int i=n; i>=0; --i){
            //0 <=> i 它们的值进行交换
            int tmp = arr[0];
            arr[0] = arr[i];
            arr[i] = tmp;
            //再继续进行堆的调整 adjust
            adjust(arr, 0, i);
        }
    }

    /**
     * 堆的调整函数,把每一个节点,和其左右孩子节点的最大值放到当前节点处
     * @param arr
     * @param i
     * @param length
     */
    private static void adjust(int[] arr, int i, int length) {
        int val = arr[i];
        for(int j=2*i+1; j<length; j=2*j+1){
            // 先用j标识值最大的孩子
            if(j+1 < length && arr[j+1] > arr[j]){
                j++;
            }

            if(arr[j] > val){
                arr[i] = arr[j];
                i = j;
            } else {
                break;
            }
        }
        arr[i] = val;
    }
}

3.归并排序

/**
 *
 * 描述: 归并排序 - 外部排序
 */
public class MergeSort {
    public static void main(String[] args) {
        int[] arr = new int[20];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random()*100);
        }
        mergeSort(arr, 0, arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    /**
     * 实现归并排序
     * @param arr
     * @param i
     * @param j
     */
    private static void mergeSort(int[] arr, int i, int j) {
        if(i < j)
        {
            int mid = (i+j)/2;
            /**
             * 以下的操作,先进行数组划分,直到划分为单个元素以后,逐级向上回溯
             * 的时候,进行合并操作
             */
            mergeSort(arr, i, mid);
            mergeSort(arr, mid+1, j);
            merge(arr, i, j); // 合并两个有序的序列
        }
    }
    /**
     * 合并两个有序的序列
     * @param arr
     * @param low
     * @param high
     */
    private static void merge(int[] arr, int low, int high) {
        int[] tmp = new int[high-low+1];
        int mid = (low+high)/2;  // i-mid mid+1-j
        int i=low; // [i, mid]
        int j=mid+1; // [mid+1, high]
        int idx=0;
        // 3 12        5 8
        while(i <= mid && j <= high){
            if(arr[i] > arr[j]){
                tmp[idx++] = arr[j++];
            } else {
                tmp[idx++] = arr[i++];
            }
        }
        while(i <= mid){  //
            tmp[idx++] = arr[i++];
        }
        while(j <= high){
            tmp[idx++] = arr[j++];
        }
        // 把tmp里面合并的有序段再写回arr的[low,high]
        for(int k=low; k<=high; ++k){
            arr[k] = tmp[k-low];
        }
    }
}

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值