java冒泡,选择,插入,希尔,归并,快速排序算法

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BasicSortDemo {
    public static void main(String[] args) {

        int[] arr = {20, 33, 5, 45, 56, 6, 7, 9, 58, 4, 34, 34, 332, 8, 43, 74, 52};//Stream.of().collect(Collectors.toList()).toArray();
//        int[] arr = {3, 4, 2, 5, 1};//Stream.of().collect(Collectors.toList()).toArray();
//        BubbleSort(arr);
//        selectSort(arr);
//        insertSort(arr);
//        shellSort(arr);
//        insertSort_front2back(arr);
//        shellSort(arr);
//        mergeSort(arr);
        speedsort(arr);
        printArray(arr);

    }

    static void BubbleSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    swap(arr, i, j);
                }
            }
        }
    }

    //选择排序,每次都取最小的放在已排序数组后面
    static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int current = arr[i];
            int minIndex = i;

            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < current) {
                    minIndex = j;
                    current = arr[j];
                }
            }
            //找到更小的,交换位置
            if (minIndex > i) {
                swap(arr, i, minIndex);
            }
        }
    }

    //插入排序,对于未排序的,每次取出一个之后向前移动,直到找到比自己小的为止.插入
    static void insertSort_back2front(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int nSortedIndex = i + 1;
            while (nSortedIndex > 0 && arr[nSortedIndex] < arr[nSortedIndex - 1]) {
                swap(arr, nSortedIndex - 1, nSortedIndex);
                nSortedIndex--;
            }
        }
    }

    //从后向前, 每个值都遍历一次,并且都向前查找位置
    static void insertSort_front2back(int[] arr) {

        for (int i = 0; i < arr.length; i++) {
            int nCurrent = arr[i];
            int npre = i - 1;
            while (npre >= 0 && arr[npre] > nCurrent) {
                arr[npre + 1] = arr[npre];
                npre--;
            }
            arr[npre + 1] = nCurrent;
        }

    }

    //希尔排序,简单插入排序的改进版,它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
    static void shellSort(int[] arr) {
        int nStartGap = ((Double) (Math.floor((arr.length / 2)))).intValue();
        for (int nStep = nStartGap; nStep > 0; nStep = nStep / 2) {
            //里面是隔着step个数的插入排序
            for (int i = nStep; i < arr.length; i++) {

                int nCurrent = arr[i];
                int nPre = i - nStep;
                //向前找位置
                while (nPre >= 0 && nCurrent < arr[nPre]) {
                    arr[nPre + nStep] = arr[nPre];
                    nPre = nPre - nStep;
                }
                arr[nPre + nStep] = nCurrent;
            }
        }
    }

    //#region 归并算法, 将数据一直拆分到每个数组只有一个元素, 然后再逐个合并数组

    static void mergeSort(int[] arr) {

        int[] res = doMergeSort(arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = res[i];
        }
    }

    static int[] doMergeSort(int[] arr) {

        if (arr.length < 2) {
            return arr;
        }
        int middle = ((Double) Math.floor(arr.length / 2)).intValue();
        int[] left = Arrays.copyOfRange(arr, 0, middle);
        int[] right = Arrays.copyOfRange(arr, middle, arr.length);

//        int[] arrT = mergeArray(doMergeSort(left), doMergeSort(right));
        int[] arrT = mergeArray_2(doMergeSort(left), doMergeSort(right));

        return arrT;
    }

    static int[] mergeArray_2(int[] left, int[] right) {

        System.out.println("");
        System.out.println("left");
        printArray(left);
        System.out.println("right");
        printArray(right);


        int i = 0, j = 0, t = 0;

        int[] res = new int[left.length + right.length];

        while (i < left.length && j < right.length) {
            if (left[i] <= right[j]) {
                res[t++] = left[i++];
            } else {
                res[t++] = right[j++];
            }
        }

        if (i >= left.length) {
            while (j < right.length) {
                res[t++] = right[j++];
            }
        }

        if (j >= right.length) {
            while (i < left.length) {
                res[t++] = left[i++];
            }
        }
        printArray(res);
        System.out.println("=====doen ====");
        return res;
    }

    static int[] mergeArray(int[] left, int[] right) {

        System.out.println("left");
        printArray(left);
        System.out.println("right");
        printArray(right);
        System.out.println("=========");
        int[] res = new int[left.length + right.length];

        int t = 0;
        int nRIghtFlag = 0;
        for (int i = 0; i < left.length; i++) {
            int nLeft = left[i];

            boolean nLeftUsed = false;
            for (int j = nRIghtFlag; j < right.length; j++) {
                if (nLeft <= right[j]) {
                    res[t++] = nLeft;
                    nLeftUsed = true;
                    break;
                } else {
                    res[t++] = right[j];
                    nRIghtFlag++;
                }
            }

            if (!nLeftUsed) {
                res[t++] = nLeft;
            }
        }
        if (nRIghtFlag < right.length) {
            for (int i = nRIghtFlag; i < right.length; i++) {
                res[t++] = right[i];
            }
        }

        printArray(res);
        return res;
    }


    //endregion

    static void speedsort(int[] arr) {
        speedSort_1(arr, 0, arr.length - 1);
    }

    static void speedSort_1(int[] arr, int start, int nend) {

        if (nend > start) {
//            int nMiddle = speedSortPartioner(arr, start, nend);
//            int nMiddle = speedSortPartioner_2(arr, start, nend);
            int nMiddle = speedSortPartioner_3(arr, start, nend);
            speedSort_1(arr, start, nMiddle);
            speedSort_1(arr, nMiddle + 1, nend);
            System.out.println(nMiddle);
        }
    }


    //方式一:
    //因为base为左边第一个元素, 所有遍历时先从右边开始,从右边找到第一个小于base的值,然后复制到左边low位置(覆盖第一个low也就是base位置)
    //然后从左边寻找第一个大于base的值,找到后移动到右边high位置(该位置为原来小于base的值),
    //如此往复,知道low不在前进了为止,此时使用base值覆盖low位置的值,完成第一次排序(小于base的都在前面,大于base的都在后面)
    static int speedSortPartioner(int[] arr, int low, int high) {
        int nBase = arr[low];
        while (low < high) {
            while (low < high && arr[high] >= nBase) {
                high--;
            }
            arr[low] = arr[high];

            //从左向右,知道找打大于base的数据
            while (low < high && arr[low] <= nBase) {
                low++;
            }
            arr[high] = arr[low];
        }

        arr[low] = nBase;

        System.out.println("low result " + low);
        printArray(arr);
        System.out.println("   ");
        System.out.println("done ");
        return low;
    }

    //
    //定义index变量,记录小于base的位置.起始位置为low
    //1.定义pointer指针从low追个遍历到high
    //2.如果pointer所指向位置小于base,则与index位置互换,index++
    //(备注index-1位置肯定是最后一个小于base值的位置)
    //3.如此遍历整个low-high所有元素
    //4.遍历结束后,互换low与index-1元素,这样保证所有小于base的值在左边,大于base的值在右边

    static int speedSortPartioner_3(int[] arr, int low, int high) {

        int pointer = low + 1, j = high;
        int index = pointer, nBase = arr[low];

//从low+1开始替换,最后low要与index替换
        while (pointer <= j) {
            if (arr[pointer] < nBase) {
                swap(arr, index, pointer);
                index++;
            }
            pointer++;
        }
        swap(arr, low, index - 1);
        return index - 1;

    }

    //快速排序方式二
    //base值这里默认为数组第一个元素.
    //1.从右边找到第一个小于base的值,从左边找到第一个大于base的值
    //2.交换low,high位置(注意是互换的两个元素分别是大于和小于base的值)
    //3.回到1,分别从右边和左边找到匹配的值,然后互换位置
    //4.如果low位置不再变化,此时low和high可能指向同一个元素或者相邻的元素
    //5.替换low位置与base的值,这样保证互换过的小于base的值都在前面,大于base的值都在后面
    //6.完成了一次排序
    static int speedSortPartioner_2(int[] arr, int low, int high) {
        int nLeftIndex = low;
        int nBase = arr[low];

        while (low < high) {
            //找到右边第一个小的
            while (low < high && arr[high] >= nBase) {
                high--;
            }

            //找到左边第一个大的
            while (low < high && arr[low] <= nBase) {
                low++;
            }

            if (low < high) {
                swap(arr, low, high);
            }
        }
        //将base上的基数与low位置替换,不管low,high是否指向同一值,因为可以判断low位置一定小于base

        swap(arr, low, nLeftIndex);

        System.out.println("low result " + low);
        printArray(arr);
        System.out.println("done  ");
        System.out.println("   ");
        return low;
    }

    static void selectSort_2(int[] arr) {
    }

    static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]);
            System.out.print(" ");
        }
        System.out.println("");
    }

    static void swap(int[] arr, int from, int to) {
        int tmp = arr[to];
        arr[to] = arr[from];
        arr[from] = tmp;
    }
}

 

posted @ 2021-03-06 10:01  龘人上天  阅读(64)  评论(0编辑  收藏  举报