选择,插入,冒泡,二分法,归并,希尔排序算法合集演示及标注

1.选择排序


理解核心思想,取出一个元素,在它后面的每一位中进行比较,选择出一个最小/最大的元素,来与它交换。


选择,插入,冒泡,二分法,归并,希尔排序算法合集演示及标注_第1张图片

代码示例

//比较
    public static boolean less(int a, int b) {
        if (a > b)
            return true;
        return false;
    }
    //交换
    public static void exch(int[] num, int i, int j) {
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }
    //排序
    public static void sort(int[] num) {
        for (int i = 0; i < num.length; i++) {
            int min = i;
            // 除开i坐标的前面的元素
            for (int j = i + 1; j < num.length; j++)
                // 注意理解这里两个比较对象。
                // 后面的每一个元素与min坐标比较。
                // 目的是找出比min坐标还小/大的值
                if (less(num[j], num[min]))
                    min = j;
            // 进行交换
            exch(num, i, min);
        }
    }


总结

第一步,设置标记

比较出最小/最大

交换标记点下标与比较的元素。


2.插入排序


理解核心思想,取出一个元素,比较它之前的元素,进行两两交换。由于一开始就是这样操作,保证了前面的数组具有有序性,从而进行交换后一样保持有序。

选择,插入,冒泡,二分法,归并,希尔排序算法合集演示及标注_第2张图片


代码示例


//比较
    public static boolean less(int a, int b) {
        if (a > b)
            return true;
        return false;
    }

    //交换
    public static void exch(int[] num, int i, int j) {
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }

    //排序
    public static void sort(int[] num) {
        for (int i = 0; i < num.length; i++) {
            //比较当前i,之前的元素,进行两两交换操作。(关键)
            for (int j = i; j > 0 && less(num[j], num[j - 1]); j--)
                exch(num, j, j - 1);
        }
    }


总结

比较两两元素,满足条件交换。


3.快速排序(二分法排序)


理解核心思想,选取第一位作为标记,经过一次排序后,将这个数组分为两个部分(无序的),左边的小于标记,右边的大于标记。选取第二位,重复上面操作。最终整个数组有序。


fd

public static void sort(int[] num) {
        sort(num, 0, num.length - 1);
    }

    public static void sort(int[] num, int left, int right) {
        int pos;
        if (left < right) {
            //算出中间位置
            pos = pos(num, left, right);
            //以中间位置进行分割成两部分
            sort(num, left, pos - 1);
            sort(num, pos + 1, right);
        }
    }

    public static int pos(int[] num, int left, int right) {
        int temp = num[left];
        while (left < right) {
            //右边开始寻找,与标记点比较
            while (left < right && num[right] >= temp)
                right--;
            //发现比标记点小。将右边的小值赋值给左边,并且将左边的下标向前移位。因为下面代码要从左边搜索了。
            if (left < right)
                num[left++] = num[right];
            //左边开始寻找,与标记点比较
            while (left < right && num[left] <= temp)
                left++;
            //发现比标记点大,将左边的大值赋值给右边,并且将右边的下标--,因为代码要从右边搜索了。
            if (left < right)
                num[right--] = num[left];
        }
        //最终完成,最后一步是左边的值赋值给右边,所以此时的left就处于中间位置。我们将标记点值赋值给它,
        num[left] = temp;
        //返回分割点。
        return left;
    }


    public static void main(String[] args) {
        int[] num = new int[20];
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            num[i] = random.nextInt(100);
        }
        sort(num);
        for (int i :
                num) {
            System.out.print(i + "\t");
        }
        System.out.println();
    }


总结

标记点

右边小的赋值给左边,左边大的赋值给右边

确定中间点,赋值标记点值,返回下标


4.希尔排序


理解核心思想,增量概念,每次在增量间比较,以及交换。缩小增量,重复比较,交换。利用的插入排序算法。

public void sort(int[] nums) {
        /** 结合了插入排序 **/
        /** 数字长度N **/
        int N = nums.length;
        /** 确认间隔长度 **/
        int h = 3;
        while (h < N / 3) h = 3 * h + 1;
        while (h >= 1) {
            /** 注意需要从i=h开始 i++ **/
            for (int i = h; i < N; i++)
            /** j=i开始 **/
                for (int j = i; j >= h && less(nums[j], nums[j - h]); j -= h)//插入排序
                    exch(nums, j, j - h);
            h = h / 3;
        }
    }


总结

理解快速排序,改变其增量即可。


5.归并排序


理解核心思想,归并排序,类似于分支法解决问题,将一个长度很长的数组,从中间分开,分成两半,取一半,重复上述操作即可。最终变成长度为2的数组,比较后,进行交换,在末端保持了有序性。继而整体保持了有序性。


    /**
     * @param nums
     */
    public void sort(int[] nums) {
        sort(nums, 0, nums.length - 1);
    }

    public void sort(int[] nums, int low, int high) {
        int mid = low + (high - low) / 2;
        if (low < high) {
            /** 左边排序 **/
            sort(nums, low, mid);
            /** 右边排序 **/
            sort(nums, mid + 1, high);
            merge(nums, low, mid, high);
        }
    }

    private 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++];
        }
        /** 拷贝合并后的数到原数组 **/
        for (int k2 = 0; k2 < temp.length; k2++)
            nums[low + k2] = temp[k2];
    }

总结

实现末端长度为2的数组,进行比较交换,保持了底层有序,进而整体有序。


  6.堆排序

理解核心思想,将数组理解成逻辑完全二叉树结构。仅仅是逻辑结构,实际还是以数组形式保存。有逻辑关系式,父节点与子节点之间关系,p(i)=c(2*i+1)|c(2*i+2),很重要。

public static void sort(int[] n) {
        for (int i = 0; i < n.length; i++) {
            createMaxHeap(n, n.length - 1 - i);
            exch(n, 0, n.length - 1 - i);
        }
    }

    public static void createMaxHeap(int[] n, int lastIndex) {
        int pIndex = (lastIndex - 1) / 2;
        for (int i = pIndex; i >= 0; i--) {
            int k = i;
            while (2 * k + 1 <= lastIndex) {
                int cIndex = 2 * k + 1;
                if (cIndex < lastIndex)
                    if (n[cIndex] < n[cIndex + 1])
                        cIndex++;
                if (n[k] < n[cIndex]) {
                    exch(n, cIndex, k);
                    k = cIndex;
                } else {
                    //关键的,跳过,上一级父节点
                    break;
                }
            }
        }
    }

总结
堆排序,没什么的说的。自己跟着代码逻辑,自己画图,理解,自然就理会了。一定要自己跟着代码走一遍。化图解。


7.计数排序

理解核心思想,统计每个元素出现的个数,然后以n-m有序数,来排序。(讲起来有点难懂)

public static void sort(int[] n) {
        int max = n[0];
        int min = max;
        for (int i = 0; i < n.length; i++) {
            if (max < n[i])
                max = n[i];
            if (min > n[i])
                min = n[i];
        }

        int[] c = new int[max - min + 1];

        for (int i = 0; i < n.length; i++) {
            c[n[i] - min] += 1;
        }
        for (int i = 0, index = 0; i < max - min + 1; i++) {
            for (int j = 0; j < c[i]; j++) {
                n[index++] = i + min;
            }
        }
    }

总结
总结什么呢?看代码理会。不懂@我

你可能感兴趣的:(java,算法)