六大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、基数排序演进及实践(学习完善中....)

1、冒泡排序

时间复杂度:O(n^2)

1.1、冒泡排序的演变过程及最终结果:

public class BubbleSort {
    public static void main(String[] args) {
        int array[] = {3, 9, -1, 10, -2};

        // 以下为冒泡数组的演变过程:

        // 1、第一趟排序,将最大的数放置在最后一位
        int temp1;
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] > array[i + 1]) {
                temp1 = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp1;
            }
        }
        System.out.println("第一次排序后的结果为:" + Arrays.toString(array));

        // 2、第二趟排序,将第二大的数放在倒数第二位
        int temp2 = 0;
        for (int x = 0; x < array.length - 2; x++) {
            if (array[x] > array[x + 1]) {
                temp2 = array[x];
                array[x] = array[x + 1];
                array[x + 1] = temp2;
            }
        }
        System.out.println("第二次排序后的结果为:" + Arrays.toString(array));

        // 3、第三趟排序,将第三大的数放在倒数第三位
        int temp3;
        for (int y = 0; y < array.length - 3; y++) {
            if (array[y] > array[y + 1]) {
                temp3 = array[y];
                array[y] = array[y + 1];
                array[y + 1] = temp3;
            }
        }
        System.out.println("第三次排序后的结果为:" + Arrays.toString(array));

        // 4、第四趟排序,将第四大的数放在倒数第四位
        int temp4;
        for (int z = 0; z < array.length - 4; z++) {
            if (array[z] > array[z + 1]) {
                temp4 = array[z];
                array[z] = array[z + 1];
                array[z + 1] = temp4;
            }
        }
        System.out.println("第四次排序后的结果为:" + Arrays.toString(array));

        System.out.println("《==============分界线================》");

        // 冒泡排序
        int arr[] = {3, 9, -1, 10, -2};
        int temp;
        for (int m = 1; m <= arr.length - 1; m++) {
            for (int n = 0; n < arr.length - m; n++) {
                if (arr[n] > arr[n + 1]) {
                    temp = arr[n];
                    arr[n] = arr[n + 1];
                    arr[n + 1] = temp;
                }
            }
        }
        System.out.println("冒泡排序结果为:" + Arrays.toString(arr));

        /**
         * 冒泡排序优化
         * 情形:例如以上代码中,可能在第三次就已经完成了顺序排列,这样第四次的排序就是多余的,造成了资源浪费
         * 做法:添加一个标识符flag,判断在本次排序中是否发生过元素位置的变动,如果没有发生过,则说明已经达到了有序的情况
         */
        // 冒泡排序
        int arr_adv[] = {3, 9, -1, 10, -2};
        int temp_adv;
        boolean flag = false;
        for (int m = 1; m <= arr_adv.length - 1; m++) {
            for (int n = 0; n < arr_adv.length - m; n++) {
                if (arr_adv[n] > arr_adv[n + 1]) {
                    // 如果进来了这个循环,则说明会发生位置变动
                    flag = true;
                    temp_adv = arr_adv[n];
                    arr_adv[n] = arr_adv[n + 1];
                    arr_adv[n + 1] = temp_adv;
                }
            }
            // 如果flag为false,则说明没有进入n循环体,即元素位置没有发生变动,此时数组是有序序列,则可以退出m循环,否则重置flag进行下一次m循环
            if (!flag) {
                break;
            } else {
                flag = false;
            }
        }
        System.out.println("冒泡排序优化结果为:" + Arrays.toString(arr_adv));
    }
}

1.2、冒泡排序实践:

public class BubbleSortTime {
    public static void main(String[] args) {
        // 生成一个80000的数组
        int[] array = new int[80000];
        for (int i = 0; i < 80000; i++) {
            array[i] = (int) (Math.random() * 800000); // 生成随机数范围:[0, 800000)
        }
        long start = System.currentTimeMillis();
        System.out.println("排序开始,请等待.......");
        int[] bubbleSort = bubbleSort(array);
        System.out.println("排序完成!");
        long end = System.currentTimeMillis();
        System.out.println("80000个数据的冒泡排序时间为: " + (end - start) + "ms");
    }

    public static int[] bubbleSort(int[] arr_adv) {
        int temp_adv;
        boolean flag = false;
        for (int m = 1; m <= arr_adv.length - 1; m++) {
            for (int n = 0; n < arr_adv.length - m; n++) {
                if (arr_adv[n] > arr_adv[n + 1]) {
                    flag = true;
                    temp_adv = arr_adv[n];
                    arr_adv[n] = arr_adv[n + 1];
                    arr_adv[n + 1] = temp_adv;
                }
            }
            if (!flag) {
                break;
            } else {
                flag = false;
            }
        }
        return arr_adv;
    }
}

结果:
六大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、基数排序演进及实践(学习完善中....)_第1张图片

2、选择

选择排序及其耗时

时间复杂度:O(n^2)

    public static void main(String[] args) {

        int[] arr = new int[100000];

        for (int i = 0; i < 100000; i++) {
            arr[i] = (int) (Math.random() * 800000);
        }
        //System.out.println("原始数组为:" + Arrays.toString(arr));
        long start = System.currentTimeMillis();
        System.out.println("开始排序,请等待....");
        for (int i = 0; i < arr.length - 1; i++) {
            // 记录最小元素的下标
            int minIndex = i;
            int temp;
            //开始寻找最小值,如果找到则将minIndex替换为此元素的下标
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    minIndex = j;
                }
            }
            // 如果minIndex数值没变,说明此元素就是剩下待排序元素的最小值,则无需调动元素
            if (minIndex != i) {
                temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
        System.out.println("排序完成!");
        long end = System.currentTimeMillis();
        System.out.println("100000个数据的选择排序总耗时: " + (end - start) + "ms");
        //System.out.println("排序完成的数组为:" + Arrays.toString(arr));
    }
}

六大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、基数排序演进及实践(学习完善中....)_第2张图片

3、插入排序

时间复杂度:O(n^2)

3.1、插入排序的演变过程及最终结果

public class InsertSort {
    public static void main(String[] args) {
        int[] arr = {101, 34, 119, 1};
        insertSortStep(arr);
        insertSort(arr);
    }

    public static void insertSortStep(int[] arr) {
        //逐步推导

        // 第一轮:{101,34,119,1} =》 {34,101,119,1}
        int insertValue = arr[1]; //开始定义第一个要插入比较的数
        int insertIndex = 1 - 1; //与第一个要插入比较的数前一个数进行比较
        //开始寻找插入位置,当insertIndex大于等于零并且插入比较的数小于前一个数时进入循环
        while (insertIndex >= 0 && arr[insertIndex] > insertValue) {
            //因为待插入数比前一个数字小,所以数据发生变更,此时结果{101,101,119,1},然后指针前移
            arr[insertIndex + 1] = arr[insertIndex];
            insertIndex--;
        }
        //当退出循环时,说明插入的位置已经找到,即为insertIndex + 1
        arr[insertIndex + 1] = insertValue;
        System.out.println("第一轮排序完成后的数组为:" + Arrays.toString(arr));

        //第二轮,和上面类似
        insertValue = arr[2]; //insertValue = 119
        insertIndex = 2 - 1;
        //此时不满足条件arr[insertIndex] > insertValue,不进入循环,即当前位置就是插入位置
        while (insertIndex >= 0 && arr[insertIndex] > insertValue) {
            arr[insertIndex + 1] = arr[insertIndex];
            insertIndex--;
        }
        arr[insertIndex + 1] = insertValue;
        System.out.println("第二轮排序完成后的数组为:" + Arrays.toString(arr));

        //第三轮,和上面类似
        insertValue = arr[3]; //insertValue = 119
        insertIndex = 3 - 1;
        while (insertIndex >= 0 && arr[insertIndex] > insertValue) {
            //第一次进入循环,数组变更为:{34,101,119,119}
            //第二次:{34,101,101,119}
            //第三次:{34,34,101,119},此时执行完循环时insertIndex = -1,不满足条件,退出循环
            arr[insertIndex + 1] = arr[insertIndex];
            insertIndex--;
        }
        arr[insertIndex + 1] = insertValue;
        System.out.println("第三轮排序完成后的数组为:" + Arrays.toString(arr));

    }

    //综上,插入排序算法如下
    public static void insertSort(int[] arr) {
        System.out.println("开始进行排序....");
        for (int i = 1; i < arr.length; i++) {
            int value = arr[i];
            int index = i - 1;
            while (index >= 0 && arr[index] > value) {
                arr[index + 1] = arr[index];
                index--;
            }
            arr[index + 1] = value;
        }
        System.out.println("结束排序,排序结果为:" + Arrays.toString(arr));
    }

}

3.2、插入排序实践

public class InsertSortTime {
    public static void main(String[] args) {
        int[] arr = new int[100000];
        for (int i = 0; i < 100000; i++) {
            arr[i] = (int) (Math.random() * 800000);
        }
        long start = System.currentTimeMillis();
        System.out.println("排序开始,请等待.......");
        int[] insertSort = insertSort(arr);
        System.out.println("排序完成!");
        long end = System.currentTimeMillis();
        System.out.println("100000个数据插入排序时间为: " + (end - start) + "ms");
        //System.out.println(Arrays.toString(arr));
    }

    public static int[] insertSort(int[] arr) {
        int value = 0;
        int index = 0;
        for (int i = 1; i < arr.length; i++) {
            value = arr[i];
            index = i - 1;
            while (index >= 0 && arr[index] > value) {
                arr[index + 1] = arr[index];
                index--;
            }
            if ( arr[index + 1] != i) {
                arr[index + 1] = value;
            }
        }
        return arr;
    }
}

六大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、基数排序演进及实践(学习完善中....)_第3张图片

4、希尔排序

时间复杂度:O(n^(2/3))

4.1、希尔排序交换式演变及实践

public class ShellSort {

    public static void main(String[] args) {
        int[] arr = new int[100000];
        for (int i = 0; i < 100000; i++) {
            arr[i] = (int) (Math.random() * 800000);
        }
        //shellSortChange(arr);
        long l = System.currentTimeMillis();
        System.out.println("开始希尔排序,请耐心等候.....");
        //int[] arrResult = shellSortChange(arr);
        int[] arrResult = shellSortMove(arr);
        System.out.println("排序完成!");
        long l1 = System.currentTimeMillis();
        System.out.println("希尔排序十万个数据总耗时:" + (l1 - l) + "ms");
    }

    //逐步推导
    public static void shellSortChange(int[] arr) {
        int temp;
        // 第一轮排序,10个元素分为5组
        for (int i = 5; i < arr.length; i++) {
            for (int j = i-5; j >=0; j-=5) {
                //如果当前元素大于步长+5后的元素,则交换位置
                if ( arr[j] > arr[j+5]) {
                    temp = arr[j];
                    arr[j] = arr[j+5];
                    arr[j+5] = temp;
                }
            }
        }
        System.out.println("第一轮排序结果为: " + Arrays.toString(arr));

        // 第一轮排序,10个元素分为5%2 = 2组
        for (int i = 2; i < arr.length; i++) {
            for (int j = i-2; j >= 0; j-=2) {
                //如果当前元素大于步长+5后的元素,则交换位置
                if ( arr[j] > arr[j+2]) {
                    temp = arr[j];
                    arr[j] = arr[j+2];
                    arr[j+2] = temp;
                }
            }
        }
        System.out.println("第二轮排序结果为: " + Arrays.toString(arr));

        // 第一轮排序,10个元素分为5%2 = 2组
        for (int i = 1; i < arr.length; i++) {
            for (int j = i-1; j >= 0; j-=1) {
                //如果当前元素大于步长+5后的元素,则交换位置
                if ( arr[j] > arr[j+1]) {
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        System.out.println("第三轮排序结果为: " + Arrays.toString(arr));

        // 希尔排序 交换式
        for (int gap = arr.length/2; gap > 0; gap /= 2) {
            for (int i = gap; i < arr.length; i++) {
                for (int j = i-gap; j >= 0; j-=gap) {
                    //如果当前元素大于步长+5后的元素,则交换位置
                    if ( arr[j] > arr[j+gap]) {
                        temp = arr[j];
                        arr[j] = arr[j+gap];
                        arr[j+gap] = temp;
                    }
                }
            }
        }
    }
}

六大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、基数排序演进及实践(学习完善中....)_第4张图片

4.2、希尔移动式实践

public class ShellSort {

    public static void main(String[] args) {
        int[] arr = new int[100000];
        for (int i = 0; i < 100000; i++) {
            arr[i] = (int) (Math.random() * 800000);
        }
        //shellSortChange(arr);
        long l = System.currentTimeMillis();
        System.out.println("开始希尔排序,请耐心等候.....");
        //int[] arrResult = shellSortChange(arr);
        int[] arrResult = shellSortMove(arr);
        System.out.println("排序完成!");
        long l1 = System.currentTimeMillis();
        System.out.println("希尔排序十万个数据总耗时:" + (l1 - l) + "ms");
    }
    
    //希尔排序 移动式
    public static int[] shellSortMove(int[] arr) {
        int value = 0;
        int index = 0;
        // 固定步长
        for (int gap = arr.length / 2; gap >= 1; gap /= 2) {
            for (int i = gap; i < arr.length; i++) {
                index = i;
                value = arr[index];
                // 如果满足条件,进行插入排序,注意和前面插入排序的区别点
                if (arr[index] < arr[index-gap]) {
                    while (index - gap >= 0 && value < arr[index - gap]) {
                        arr[index] = arr[index - gap];
                        index -= gap;
                    }
                    // 找到位置,插入
                    arr[index] = value;
                }
            }
        }
        return arr;
    }
}

六大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、基数排序演进及实践(学习完善中....)_第5张图片
(震惊!!!)

---------------more------------------
待补充…

你可能感兴趣的:(Java进阶自学笔记,排序算法,算法,数据结构)