• 算法思想篇排序


     递进的方式 

      插入,希尔,归并

      冒泡,选择,快速

      堆排序(树里)

    一:分析排序

    1.哪几个方面

      时间效率

      空间效率

      交换次数

      稳定性

    2.稳定性的意义

      

    二:插入排序

    1.理解

      可以理解成抓牌

    2.代码

    package com.jun.algorithm.foundation.thought;
    
    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * 插入排序
     * 例如打牌场景就是如此
     * <p>
     * 具体的步骤:
     * 将数组分成已排序段和未排序段,初始化已排序段只有一个元素
     * 到未排序段取元素插入已排序段,保证有序
     * 重复上述操作
     * <p>
     * 稳定性:稳定
     *
     * @author caojun
     */
    public class InsertSort {
        /**
         * 排序
         * 时间复杂度
         * n^2,最好的情况是n
         *
         * @param arr 要排序的数组
         * @return 排序后的数组
         */
        private int[] insert(int[] arr) {
            // 从1开始,第一个不要排序,数组从i进行分开
            for (int i = 1; i < arr.length; i++) {
                int data = arr[i];
                // 将数据插入到已经排好序段,从尾往头进行比较,可以降低时间复杂度,即是break
                // j从i-1开始,就是从当前的前一个开始,与当前的数据进行比较
                int j;
                for (j = i - 1; j >= 0; j--) {
                    if (arr[j] > data) {
                        arr[j + 1] = arr[j];
                    } else {
                        break;
                    }
                }
                // 赋值
                arr[j + 1] = data;
            }
            return arr;
        }
    
        @Test
        public void test() {
            int[] arr = {1, 3, 2, 7, 5};
            int[] newArr = insert(arr);
            System.out.println(Arrays.toString(newArr));
        }
    
    }

    三:希尔排序

    1.思想

      按照几个分段进行排序

      目标就是让更多的数据已经排序好。

    2.程序

    package com.jun.algorithm.foundation.thought;
    
    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * 希尔排序
     * 把记录按照下标进行增量分组,对每一组使用插入排序算法排序
     * 随着增量的减少,每组包含的有序的原来越多,当增量减少为1时,整个文件分为一组,算法终止
     * <p>
     * 稳定性:不稳定
     *
     * @author caojun
     */
    public class ShellSort {
        private int[] shell(int[] arr) {
            // 分段
            for (int add = arr.length / 2; add >= 1; add /= 2) {
                for (int i = add; i < arr.length; i++) {
                    int data = arr[i];
                    int j;
                    // 间隔之后,进行前后对比
                    for (j = i - add; j >= 0; j -= add) {
                        if (arr[j] > data) {
                            arr[j + add] = arr[j];
                        } else {
                            break;
                        }
                    }
                    // 赋值
                    arr[j + add] = data;
                }
    
            }
            return arr;
        }
    
        @Test
        public void test() {
            int[] arr = {1, 3, 2, 7, 5};
            int[] newArr = shell(arr);
            System.out.println(Arrays.toString(newArr));
        }
    }

    四:归并排序

    1.思路

      将待排序的数组分为两个字数组,分别对它们按同样的方式进行排序,最后将两个有序子数组 归并成一个有序数组。

      

      

    2.程序

    package com.jun.algorithm.foundation.thought;
    
    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * 归并排序
     * 递归与分治的思想结合
     * <p>
     * 时间复杂度是nlogn
     * <p>
     * 稳定性:稳定的,因为是对插入排序的优化
     *
     * @author caojun
     */
    public class MergeSort {
        /**
         * 排序
         *
         * @param arr   数组
         * @param left  数组的左端
         * @param right 数组的右端
         * @return 排序后的数组
         */
        public int[] merge(int[] arr, int left, int right) {
            // 相等了就表示只有一个数了,不用再分了,终止条件
            if (left < right) {
                int mid = (left + right) / 2;
                merge(arr, left, mid);
                merge(arr, mid + 1, right);
                //
                mergeData(arr, left, mid, right);
            }
            return arr;
        }
    
        private void mergeData(int[] arr, int left, int mid, int right) {
            // 保存合并后的数据
            int[] temp = new int[arr.length];
            // 左边的第一个数据的位置
            int point1 = left;
            // 右边的第一个数据的位置
            int point2 = mid + 1;
            // 表示已经到达的位置
            int loc = left;
    
            // 合并的终止条件
            while (point1 <= mid && point2 <= right) {
                if (arr[point1] < arr[point2]) {
                    temp[loc] = arr[point1];
                    point1++;
                    loc++;
                } else {
                    temp[loc] = arr[point2];
                    point2++;
                    loc++;
                }
            }
            // 还有一个数组没有进行将数据合并在,这里是左边没有赋值完
            while (point1 <= mid) {
                temp[loc++] = arr[point1++];
            }
            // 还有一个数组没有进行将数据合并在,这里是右边没有赋值完
            while (point2 <= right) {
                temp[loc++] = arr[point2++];
            }
    
            // 将临时数组中的数据添加到arr中
            if (right + 1 - left >= 0) {
                System.arraycopy(temp, left, arr, left, right + 1 - left);
            }
        }
    
        @Test
        public void test() {
            int[] arr = {1, 5, 6, 3, 8};
            int[] newArr = merge(arr, 0, arr.length - 1);
            System.out.println(Arrays.toString(newArr));
        }
    }

    五:选择排序

    1.思路

      班级找最高的人。

      每次从未排序的区间中找到最小的元素,将其放到已排序区间的末尾,但是不是插入那种方式进行移动数组,选择进行交换。

      

    2.程序

    package com.jun.algorithm.foundation.thought;
    
    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * 选择排序
     * 使用场景:在班级中选择出身高最高的人
     *
     * 时间复杂度:
     *
     * @author caojun
     */
    public class SelectSort {
    
        public int[] select(int[] arr) {
            for (int i = 0; i < arr.length; i++) {
                // 循环的那个就是找到一个最小的
                int min = i;
                for (int j = i + 1; j < arr.length; j++) {
                    if (arr[j] < arr[min]) {
                        min = j;
                    }
                }
                // 交换
                int temp = arr[min];
                arr[min] = arr[i];
                arr[i] = temp;
            }
            return arr;
        }
    
        @Test
        public void test() {
            int[] arr = {1, 3, 2, 7, 5};
            int[] newArr = select(arr);
            System.out.println(Arrays.toString(newArr));
        }
    
    }

    六:冒泡排序

    1.思路

      冒泡的方式

      

    2.程序

    package com.jun.algorithm.foundation.thought;
    
    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * 冒泡排序
     * 每次都和相邻的元素进行比较
     *
     * @author caojun
     */
    public class BubbleSort {
        public int[] bubble(int[] arr) {
            int n = arr.length;
            for (int i = 0; i < n - 1; i++) {
                for (int j = 0; j < n - 1 - i; j++) {
                    if (arr[j] > arr[j + 1]) {
                        int temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            return arr;
        }
    
        @Test
        public void test() {
            int[] arr = {1, 3, 2, 7, 5};
            int[] newArr = bubble(arr);
            System.out.println(Arrays.toString(newArr));
        }
    }

    七:快速排序

    1.思路

         先分成三个部分,左边,基准数,右边

      然后,分别递归左边与右边的书。

    2.程序

    package com.jun.algorithm.foundation.thought;
    
    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * 快速排序
     *
     * @author caojun
     */
    public class QuickSort {
        /**
         * 排序
         * 每次确定一个中间位置,当每个中间位置都确定return之后,程序也就运行结束了
         *
         * @param arr   数据
         * @param left  左边位置
         * @param right 右边位置
         */
        public void quick(int[] arr, int left, int right) {
            if (left > right) {
                return;
            }
            int base = arr[left];
            int ll = left;
            int rr = right;
    
            while (ll != rr) {
                // 找到右边比基准数据小的数据
                while (ll < rr && arr[rr] >= base) {
                    rr--;
                }
                // 找到左边比基准数据大的数据
                while (ll < rr && arr[ll] <= base) {
                    ll++;
                }
                if (ll < rr) {
                    int temp = arr[rr];
                    arr[rr] = arr[ll];
                    arr[ll] = temp;
                }
            }
            // 调整基准点到中间位置,因为后左边查询,所以中间值是ll
            arr[left] = arr[ll];
            arr[ll] = base;
            // 进行下一轮。这个时候,不考虑ll位置数据,因为ll位置已经是正确的了
            quick(arr, left, ll - 1);
            quick(arr, ll + 1, right);
        }
    
        @Test
        public void test() {
            int[] arr = {1, 3, 2, 7, 5};
            quick(arr, 0, arr.length - 1);
            System.out.println(Arrays.toString(arr));
        }
    }
  • 相关阅读:
    烟台的两大建筑均初具规模,看一看现在的样子。
    ExpressBars Suite V6.29的安装
    又是一年返乡时,春运又开始了!
    C# 3.0新特性之扩展方法
    ObservableCollection<T> 类
    ControlTemplate和ItemTemplate的区别
    teechart属性和方法
    UpdateSourceTrigger 属性控制绑定源更新的执行时间
    "Lc.exe已退出 代码为1 "
    ObservableCollection 类
  • 原文地址:https://www.cnblogs.com/juncaoit/p/16093052.html
Copyright © 2020-2023  润新知