冒泡排序、选择排序、插入排序、希尔排序、快速排序

冒泡排序

冒泡排序
这张图镜像了,当然也可以看明白,再赋另一张图
冒泡排序

    public void maoPao(int[] nums) {
        // 两两相邻比较,得到极值
        // 升序,每一次比较 得到一个最大值,移动到最后
        for (int i = 0; i < nums.length - 1; i++) {
            // 第一层遍历的次数

            for (int j = 0; j < nums.length - i - 1; j++) {
                // 第二层遍历的元素
                if (nums[j] > nums[j + 1]) {
                    int tem = nums[j + 1];
                    nums[j + 1] = nums[j];
                    nums[j] = tem;
                }
            }
        }

        System.out.println(Arrays.toString(nums));
    }

选择排序

选择排序

选择排序

    public void chooseSoft(int[] nums) {
        // 选择排序
        // 遍历依次取出每一项,和后面的每一项比较,得到最大值或者最小值,交换移动
        // 升序就是获取最小值
        for (int i = 0; i < nums.length; i++) {
            int index = i;
            for (int j = i; j < nums.length - 1; j++) {
                if (nums[index] > nums[j + 1]) {
                    index = j + 1;
                }
            }
            int temp = nums[index];
            nums[index] = nums[i];
            nums[i] = temp;
        }
        System.out.println(Arrays.toString(nums));

    }

插入排序

   // 快速排序;
    // 定一个基准点,一般以左侧为基准点,两个指针(i,j右侧),
    // 先j-->左,遇到小于基准点停下,再i-->右,遇到大于基准点,交换两个元素。
    // 再次 移动j和i相同操作,直到j==i,这时交换这个点和基准点,
    // 这个时候,数组排序: 左侧为 小于基准点,右侧大于基准点。
    // 递归同样的操作

图一:
插入排序
图二:
插入排序
这里写了两种实现方式:依次对应图一和图二

    public void insertSoft(int[] nums) {
        // 插入排序(可以看成 两个序列:排好序的、无序的)
        // 首次可以把第一个元素看成是 有序的
        // 遍历规则:
        // 从头到尾依次获取无序的每一项,和之前有序的数比较,直到插入有序序列的适当位置。
        // (如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
        // 升序

        // 第一种方法:两两交换,直到满足---图一
        for (int i = 1; i < nums.length; i++) {
            for (int j = i; j > 0; j--) {
                if (nums[j] < nums[j - 1]) {
                    int tem = nums[j - 1];
                    nums[j - 1] = nums[j];
                    nums[j] = tem;
                }
            }
        }
        
        System.out.println("one->"+Arrays.toString(nums));
        // 第二种方法:更新大于的值,最后更新实际得到index下标的值 ---图二
        for (int i = 1; i < nums.length; i++) {
            // 默认插入的下标
            int index = i;
            // 需要比较的值
            int indexValue = nums[i];
            for (int j = i; j > 0; j--) {
                // 依次比较排序好的元素
                if (indexValue < nums[j - 1]) {
                    // 更新 index 所在的值
                    nums[index] = nums[j - 1];
                    index--;
                }
            }
            // 插入完成之后,得到 indexValue 对应的下标 index;
            // 更新值
            nums[index] = indexValue;
        }

        System.out.println("two->"+Arrays.toString(nums));
    }

希尔排序

希尔排序
希尔排序

希尔排序参考连接:https://www.cnblogs.com/chengxiao/p/6104371.html

    public void xeSoft(int[] nums) {
        // 在希尔排序的理解时,我们倾向于对于每一个分组,
        // 逐组进行处理,但在代码实现中,
        // 我们可以不用这么按部就班地处理完一组再调转回来处理下一组(这样还得加个for循环去处理分组)
        // 比如[5,4,3,2,1,0] ,
        // 首次增量设gap=length/2=3,则为3组[5,2] [4,1] [3,0],
        // 实现时不用循环按组处理,我们可以从第gap个元素开始,逐个跨组处理。
        // 同时,在插入数据时,可以采用元素交换法寻找最终位置,
        // 也可以采用数组元素移动法寻觅。希尔排序的代码比较简单,如下:
        // 希尔排序,不稳定,不常 gap


        // 循环 递减二倍步长
        for (int gap = nums.length / 2; gap > 0; gap /= 2) {

            for (int i = gap; i < nums.length; i++) {
                int j = i;
                while (j - gap >= 0 && (nums[j] < nums[j - gap])) {
                    // 交换
                    int tem = nums[j];
                    nums[j] = nums[j - gap];
                    nums[j - gap] = tem;
                    j -= gap;
                }
            }
        }
        System.out.println(Arrays.toString(nums));
    }

快速排序

图一:
快速排序

    // 解法一:对应图一
    private void quickSoft(int[] nums, int start, int end) {
        System.out.println("start:" + start + "\t end" + end);
        // 出口
        if (start > end) {
            return;
        }
        int index = start;
        int lastIndex = end;
        int startValue = nums[start];
        while (index < lastIndex) {
        	 // 需要注意的是 正向和反向遍历查找时,只能存在一种等于startValue的判断
            // 比如 nums[lastIndex] > startValue与nums[index] <= startValue
            // 不能同时等于,比如 552477458,这样最前面的5和倒数第二个5,会一直循环
            // 如果非要这样,可以在 交换之后,j--操作
            while (nums[lastIndex] > startValue && lastIndex > index) {
                lastIndex--;
            }
            while (nums[index] <= startValue && index < lastIndex) {
                index++;
            }
            int tem = nums[index];
            nums[index] = nums[lastIndex];
            nums[lastIndex] = tem;
        }
        // 跳出循环说明,两者相等,交换基准和该点
        if (start != index) {
            int tem = nums[start];
            nums[start] = nums[index];
            nums[index] = tem;
        }

        // 操作左边
        quickSoft(nums, start, index - 1);
        // 操作右边
        quickSoft(nums, index + 1, end);

    }
	
	// 开始调用:
	// quickSoft(nums, 0, nums.length - 1);

图二:
快速排序

    // 解法二:类似双指针,减少循环
    public void quickSoftDouble(int[] nums, int start, int end) {
        if (start > end) return;
        int startValue = nums[start];
        int index = start + 1;
        // 这里的index 相当于慢指针
        for (int i = index; i <= end; i++) {
            // 遍历 找到小于基准值的数据,和当前慢指针index更换数据值
            if (nums[i] < startValue) {
                int tem = nums[i];
                nums[i] = nums[index];
                nums[index] = tem;
                // 增加下标值
                index++;
            }
        }
        // 当循环结束时,index 指针 指向了数组nums在范维index-end中,第一个不小于startValue值的 对应下标的值,所以应该操作index-1
        // 如果没有找到小于startValue的,则index = start + 1,
        // 交换 start 和 index-1 的值
        int tem = nums[start];
        nums[start] = nums[index - 1];
        nums[index - 1] = tem;

        // 递归
        // 左
        quickSoftDouble(nums, start, index - 1 - 1);
        // 右
        quickSoftDouble(nums, index, end);
    }

	// 开始调用:
	// quickSoftDouble(nums, 0, nums.length - 1);

参考链接:
1.RUNOOB.COM:算法系列
2.https://www.cnblogs.com/ll409546297/p/10956960.html
3.https://www.cnblogs.com/chengxiao/p/6104371.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值