排序算法(插入)

package com.anji.allways.business.sales.service.impl;

import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * <pre>
 *  排序算法
 * </pre>
 *
 * @author shenke
 * @version $Id: AddressController.java, v 0.1 2019年6月19日 上午9:51:39 shenke Exp $
 */
@Component
public class Sort {

    /**
     * 冒泡排序
     * 逻辑:比较相邻元素,大者右移
     * 外层循环代表元素个数,需要进行的排序次数;
     * 内层循环:比较数组中相邻元素大小,从a[0]开始,a[a.length-1-i]结束,随着外层循环进行,内层循环次数逐次减少
     * 注意:如a[5,4,3,2,1] i < a.length-1 即 (i < 4) 非 i < a.length (i < 5),因为循环从0开始,0-3还是循环4次,n个元素,外层循环n-1次
     *
     * @return
     */
    public static int[] maopaoSort(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - 1 - i; j++) {
                if (a[j] > a[j + 1]) {
                    swap(a, j, j + 1);
                }
            }
        }
        return a;
    }

    public static void swap(int[] a, int n, int m) {
        int temp;
        temp = a[n];
        a[n] = a[m];
        a[m] = temp;
    }

    public static void main(String[] args) {
        int[] maopao = {3, 2, 1};
        int[] insert = {6, 5, 4};
        int[] insertTwo = {3, 2, 8, 1, 9, 5, 4, 7};
        int[] insertThree = {3, 2, 8, 1};
        //maopaoSort(maopao);
        //insertSortOne(insert);
        insertSotTwo(insertThree);
        //insertSortThree(insertThree);
        //insertSortFour(insertThree);
        //System.out.println("冒泡排序后:" + Arrays.toString(maopao));
        //System.out.println("插入排序后:" + Arrays.toString(insert));
        System.out.println("插入排序2后:" + Arrays.toString(insertThree));
        //System.out.println("插入排序3后:" + Arrays.toString(insertThree));
        //System.out.println("插入排序4后:" + Arrays.toString(insertThree));

    }

    /**
     * 插入排序(四种实现方式)
     * <p>
     * 中心思想:向前比较 代码实现方式 j = i j--
     *
     * <p>
     * int[] a = {3, 2, 8, 1};
     * 逻辑:交换的方式实现(当前元素向前交换)
     * 1,j = 1,初次循环:假定第一个元素位置正确,新元素a[1]与第一个元素比较,a[j-1=0]>a[j=1],交换a[0] a[1]
     * 2,后续循环:外层循环2,(外层循环1 处理后 a = {2, 3, 8, 1})
     * 2.1)内层循环1(j = i = 2 假定a[2]为目标元素),a[2] = 8 大于a[1] = 3,因为取a[2] = 8时,其前面元素都是已经排好序的,后续无需再作比较
     * 2.2)内层循环2(j = i = 1 假定a[1]为目标元素),a[1] = 3 大于a[0] = 2 (不需要)
     * 3,外层循环3 (2处理后 a = {2, 3, 8, 1})
     * 3.1)内层循环1(j = i = 3 假定a[3]为目标元素),交换a[3] a[2] a = {2, 3, 1, 8}
     * 3.2)内层循环2(j = i = 2 假定a[2]为目标元素),交换a[2] a[1] a = {2, 1, 3, 8}
     * 3.3)内层循环3(j = i = 1 假定a[1]为目标元素),交换a[1] a[0] a = {1, 2, 3, 8}
     * <p>
     * 交换方式与移动方式区别
     * 不同
     * 每次循环,比较并交换,新元素的下标不停的变动 vs 后移大数,循环结束,确定新元素的下标
     *
     * @return
     */
    public static int[] insertSortOne(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int j = i;
            while (j > 0 && a[j] < a[j - 1]) {
                swap(a, j, j - 1);
                j--;
            }
        }
        return a;
    }


    /**
     * int[] a = {3, 2, 8, 1};
     * 逻辑:交换的方式实现(当前元素向后交换)
     * 1,外层循环1 i = 0,j < 0 内层不执行
     * 2,外层循环2 i = 1
     * 2.1)j = 0 a[0] a[1]比较,a = {2, 3, 8, 1}
     * 3,外层循环3 i = 2
     * 3.1)j = 1 a[1] a[2]比较 a = {2, 3, 8, 1}
     * 3.2)j = 0 a[0] a[1]比较 a = {2, 3, 8, 1}
     * 4,外层循环4 i = 3
     * 4.1)j = 2 a[2] a[3]比较 a = {2, 3, 1, 8}
     * 4.2)j = 1 a[1] a[2]比较 a = {2, 1, 3, 1}
     * 4.3)j = 0 a[0] a[1]比较 a = {1, 2, 3, 1}
     * <p>
     * 比较方法3不同之处
     * 相同
     * 1,都有新元素的概念
     * 2,都是默认第一个元素a[0]已排好
     * 3,新元素来到前,前面的元素已排好序
     * 4,都是向前比较 通过j--控制
     * <p>
     * 不同
     * 1,控制新元素方式:j=i-1 vs j=i
     * 2,每次循环,新元素的下标不停的变动 vs 循环结束,确定新元素的下标
     * 3,交换元素位置 vs 后移元素位置
     * <p>
     * 特别注意:内层循环:如i = 2 for(int j = i - 1 j >= 0 j--)会执行两次,每次j是会递减的,不是i = 2,每次执行循环j = i -1 都等于1,所以int j = i-1仅仅是给j一个初始值
     *
     * @param a
     * @return
     */
    public static int[] insertSotTwo(int[] a) {
        for (int i = 0; i < a.length; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (a[j] > a[j + 1]) {
                    swap(a, j, j + 1);
                } else {
                    break;
                }
            }
        }
        return a;
    }

    /**
     * [] a = {3, 2, 8, 1};
     * 思想:
     * 1,j = 1,,第一个新元素来了a[1],假定第一个元素(目标元素)的位置正确,即a[0],新拿到扑克a[1],与第一个元素a[0]比较
     * 1.1)a[1] > a[0] 假设正确
     * 1.2)a[1] < a[0](3 > 2>) 大数后移,把大数a[0]给a[1],j-- = 0,循环结束,新元素给到正确的位置a[0],处理后 a = {2, 3, 8, 1}
     * 2,比较移动,不是比较交换(大数后移,循环结束后,找到目标元素正确位置,给值)
     * 3,j = 2,第二个新元素来了a[2],a[1]处理后:int[] a = {2, 3, 8, 1};
     * 3.1)理解为手里有扑克2,3,现在拿到扑克8放在哪个位置,而且手里的牌排序永远正确
     * 3.2)目标元素 a[2] = 8,8与a[1]=3比较,8与a[0]=2比较,均大于;既然前面都是排好的,只比较目标元素前一个即可(循环结束,新元素8的下标正确a[2])。
     * 3.3)j = 3,第三个个新元素来了a[3]=1,与a[2]比较,a[2]>a[3],后移a[2](把a[2]=8 给到a[3]位置),同时记录新元素正确下标(3-1=2)
     * (且注意a[2]=8,还是之前的数据,并没有被新元素1取代),排序后 int[] a = {2, 3, 8, 8};
     * j = 2,继续执行循环,《注意:每次比较都是拿新元素target a[3]=1,与前面元素作比较》,目标元素target值与a[j-1=1]比较,a[1]=3>1,3后移 a[2]=3,此时int[] a = {2, 3, 3, 8},j-- = 1
     * j = 1,target=1,与a[1-1=0]=2比较,a[0]=2 > 1,后移2,a[j=1]=2,此时int[] a = {2, 2, 3, 8},j-- = 0
     * j = 0,循环结束,target的正确下标j = 0,a[0]=1,此时int[] a = {1, 2, 3, 8}
     * 4,拿到的新扑克(即数组中需要进行排序的数据),与手里已经排序的扑克(即目标数据前面的数据)比较
     * 4.1)当前元素小于前一个元素,逐个比较
     * 4.2)当前元素大于前一个元素,即大于前面所有元素,结束循环(方法4优化)
     * <p>
     * 再总结:
     * 1,一直是拿新元素与前面所有元素比较,后移比它大的元素
     * 2,不断定位到新元素的正确下标
     * 3,循环结束,把新元素给到正确下标
     *
     * @param a
     */
    public static void insertSortThree(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int j = i;
            int target = a[i];// 目标元素(新拿到扑克)
            while (j > 0 && target < a[j - 1]) {//比较目标元素和前面每一个元素
                a[j] = a[j - 1];// 后移大数
                j--;// 目标元素正确位置
            }
            a[j] = target;// 目标元素给到正确位置
        }
    }

    /**
     * 优化 for 代替 while 添加break
     * int[] a = {3, 2, 8, 1}
     * 逻辑:
     * 1,当前元素大于前一个元素,即大于前面所有元素,结束循环
     *
     * @param a
     */
    public static void insertSortFour(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int target = a[i];// 目标元素(新拿到扑克)
            int j = i;
            for (; j > 0; ) {//注意此处循环写法
                //for (int j = i; j > 0; ) { 错误写法 j在变动
                if (target < a[j - 1]) {//比较目标元素和前面每一个元素
                    a[j] = a[j - 1];// 后移大数
                    j--;// 目标元素正确位置
                } else {
                    break;
                }
                a[j] = target;// 目标元素给到正确位置
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值