算法学习(一)——插入排序

插入排序

一步一步思考,拆分,由浅入深:

  1. 先找出最小值,小循环没啥大问题再进入下一步,再去思考边界问题。

    int minPos = 0;
    // 一步一步思考,先获取最小值
    for (int i = 0; i < arr.length; i++) {
        minPos = arr[i] < arr[minPos] ? i : minPos;
    }
    
  2. 进行大循环

    int[] arr = {2, 8, 4, 5, 7, 6, 3, 1, 9};
    for (int j = 0; j < arr.length - 1; j++) {
        int minPos = j;
        // 小循环——找出最小值的下标,并让minpos指向它
        for (int i = j + 1; i < arr.length; i++) {
            minPos = arr[i] < arr[minPos] ? i : minPos;
        }
        System.out.println("minPos:" + minPos);
        // 最小值放到本次循环的第一位
        swap(arr, j, minPos);
    }
    

代码:

// 选择排序-最简单但最没用
// 平均时间复杂度: n^2 
// 空间复杂度: 1 
// 稳定性: 不稳定
public class SelectionSort {
    public static void main(String[] args) {
        int[] arr = {2, 8, 4, 5, 7, 6, 3, 1, 9};
        for (int j = 0; j < arr.length - 1; j++) {
            int minPos = j;
            // 一步一步思考,先获取最小值
            for (int i = j + 1; i < arr.length; i++) {
//				if(arr[i]<arr[minPos]) {
//					minPos=i;
//				}
//				简化
                minPos = arr[i] < arr[minPos] ? i : minPos;
            }
            System.out.println("这是第" + j + "次循环后的数组:");
            PrintArr(arr);
            System.out.println("minPos:" + minPos);
            // 最小值放到第一位
            swap(arr, j, minPos);
        }

    }

    // 打印一维数组
    public static void PrintArr(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    // 数组元素交换位置
    public static void swap(int[] arr, int i, int minPos) {
        int temp = arr[i];
        arr[i] = arr[minPos];
        arr[minPos] = temp;
    }
}

大O分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6otqEGUJ-1647693006497)(images/image-20220317214705184.png)]

最后算得:

n^2/2 - n/2 + T(常数)

以为就算时间复杂度是在大规模计算的前提下,所以计算时间复杂度记得:

  • 忽略常数项
  • 忽略低次项

所以为 O(n^2)

稳定性:不稳定

两个相同的数,排序先后次序可能发生变化。

改良版:

/**
[选择排序 改良版]:
	使用了两个指针,一个min 一个max在原本的基础上减少了一半循环
[测试用例]:
	int[] arr = {2, 8, 4, 5, 7, 6, 3, 9, 1};
测试过程:
	for:0 8
	end:0 1
	for:0 1
	end:0 1
	for:0 1
	end:0 1
	for:0 1
	end:0 1
	for:0 1
	end:0 1
	for:0 1
	end:0 1
	for:0 1
	end:0 7
	[第0次]:1 8 4 5 7 6 3 2 9 
	for:1 7
	end:1 7
	for:1 7
	end:1 7
	for:1 7
	end:1 7
	for:1 7
	end:1 7
	for:1 7
	end:1 7
	[第1次]:1 2 4 5 7 6 3 8 9 
	for:2 6
	end:2 3
	for:2 3
	end:2 4
	for:2 4
	end:2 4
	[第2次]:1 2 3 5 4 6 7 8 9 
	for:3 5
	end:4 5
	[第3次]:1 2 3 4 5 6 7 8 9 
 */
public class SelectionSort {
    public static void main(String[] args) {
        int[] arr = {2, 8, 4, 5, 7, 6, 3, 9, 1};
        for (int i = 0; i < arr.length / 2; i++) {
            int minpos = i;
            int maxpos = arr.length - i - 1;
            if (arr[minpos] > arr[maxpos]) {
                    swap(arr, minpos, maxpos);
            }
            for (int j = i + 1; j < arr.length - i - 1; j++) {
                System.out.println("for:" + minpos + " " + maxpos);
                // 因为min和max在循环中是取不到的,所有要 先 比较二者大小
                // 比如第二圈循环
                // minpos=1 maxpos=7
                // arr[minpos]=8 arr[maxpos]=2
                // 如果没有这个判断,就会在下面两个if中让minpos和minpos=2 对应的值为4,
                // 而在接下来的循环中因为不在出现8和2 
                // 导致排序出现问题。
//				if (arr[j]<arr[minpos]) {
//					minpos=j;
//				}
                // 简化:
                minpos = arr[j] < arr[minpos] ? j : minpos;
//				if(arr[j]>arr[maxpos]) {
//					maxpos = j;
//				}
                // 简化:
                maxpos = arr[j] > arr[maxpos] ? j : maxpos;
                System.out.println("end:" + minpos + " " + maxpos);
            }
            swap(arr, i, minpos);
            swap(arr, arr.length - i - 1, maxpos);
            System.out.print("[第" + i + "次]:");
            printArr(arr);
            System.out.println();
        }
    }

    static void printArr(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    static void swap(int[] arr, int i, int minPos) {
        int temp = arr[i];
        arr[i] = arr[minPos];
        arr[minPos] = temp;
    }
}

验证算法——对数器

如何验算你的算法是否正确?

  1. 肉眼观察
  2. 产生足够多随机样本
  3. 用确定正确的算法计算样本结果
  4. 对比被验证算法的结果
public class DateChecker {
    // 初始化一个10000长度的数组
	static int[] generateRandomArray() {
		Random random = new Random();
		int[]arr= new int[10000];
		for (int i = 0; i < arr.length; i++) {
			arr[i]=random.nextInt(10000);
		}
		return arr;
	}
    // 检查函数
	static void check() {
		int [] arr = generateRandomArray();
		int [] arr2 = new int[arr.length];
		System.arraycopy(arr, 0, arr2, 0, arr.length);
		Arrays.sort(arr);
		SelectSort(arr2);
		boolean same = true;
		for (int i = 0; i < arr2.length; i++) {
			if (arr[i]!=arr2[i]) {
				System.out.println(arr[i]+" "+arr2[i]);
				same=false;
			}
		}
		System.out.println(same==true?"right":"wrong");
	}
	// 选择排序
	static void SelectSort(int[] arr) {
		for (int i = 0; i < arr.length / 2; i++) {
            int minpos = i;
            int maxpos = arr.length - i - 1;
            if (arr[minpos] > arr[maxpos]) {
                swap(arr, minpos, maxpos);
            }
            for (int j = i + 1; j < arr.length - i - 1; j++) {
                minpos = arr[j] < arr[minpos] ? j : minpos;
                maxpos = arr[j] > arr[maxpos] ? j : maxpos;
            }
            swap(arr, i, minpos);
            swap(arr, arr.length - i - 1, maxpos);
        }
    }
    // 打印数组
    static void printArr(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
    // 互换值
    static void swap(int[] arr, int i, int minPos) {
        int temp = arr[i];
        arr[i] = arr[minPos];
        arr[minPos] = temp;
    }
    // 主函数
    public static void main(String[] args) {
		for (int i = 0; i < 1000; i++) {
			check();
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值