一、数组排序

1. 冒泡排序

每两个元素比较,按照从小到大顺序时,两两找出较大值,可能会发生交换,将较大值放在右侧,按照从大到小顺序时,两两比较找出较小值,可能会发生交换,将较小值放在右侧

  • 代码实现
// TODO 冒泡排序
		int[] a = { 34, 23, 77, 66, 3, 145 };
		// 排序的次数:数组元素的个数减一
		for (int i = 0; i < a.length - 1; i++) {
			// j的取值为当前数组能够取到的下标减去已经排好的数(已经执行排序的次数)
			for (int j = 0; j < a.length - 1 - i; j++) {
				// 两个数字的比较,是否交换
				// 从左至右,从小到大
				if (a[j] > a[j + 1]) {
					a[j] = a[j] ^ a[j + 1];
					a[j + 1] = a[j] ^ a[j + 1];
					a[j] = a[j] ^ a[j + 1];
				}
			}
		}

2. 选择排序

冒泡算法的改进,每次从当前比较的一组数中选出最值,排好一个数,只进行一次交换

  • 代码实现
// TODO 选择排序
		int[] a = { 34, 23, 77, 66, 3, 145 };
		// 排序的次数:数组元素的个数减一
		for (int i = 0; i < a.length - 1; i++) {
			// 每次指向a[0]
			int max = 0;
			// j的取值为当前数组能够取到的下标减去已经排好的数(已经执行排序的次数)
			for (int j = 1; j < a.length - i; j++) {
				// 使用max记录当前比较中较大的数
				// 从左至右,从小到大
				if (a[j] > a[max]) {
					max = j;
				}
			}
			// 将当前获取到的较大的数放在相应的位置
			// a ^ a = 0(亦或运算->相同为0,不同为1)
			if (max != a.length - i - 1) {
				/*int temp = a[max];
				a[max] = a[a.length - i - 1];
				a[a.length - i - 1] = temp;*/
				a[max] = a[max] ^ a[a.length - i - 1];
				a[a.length - i - 1] = a[max] ^ a[a.length - i - 1];
				a[max] = a[max] ^ a[a.length - i - 1];
			}
		}

3. Arrays工具类

  • Arrays所在包:java.util
  • sort方法:将数组的元素按照自然序列排序(基本数据类型),也可以自定义排序规则
  • 使用规则:无返回值类型,直接传入数组变量作为参数
int a[] = {25,66,7,8,43,200}
Arrays.sort(a);

二、数组查找(二分法)

在一个有序数组中查找一个数,返回其所在位置

  • 代码实现
// TODO 有序数组的二分查找
		int[] a = {3,20,10,5,67,103};
		Arrays.sort(a);
		for (int i : a) {
			System.out.print(i + "  ");
		}
		System.out.println();
		System.out.println("请输入要查找的数:");
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		// 初始化用于标记区间的变量
		int left = 0;
		int right = a.length - 1;
		// 初始化每次用于比较的变量的下标
		int middle = (left + right) / 2;
		// 标记是否已经找到相应的数字
		int location = -1;
		while(left <= right) {
			if (a[middle] == n) {
				// 找到时标记位置,并且跳出
				location = middle;
				break;
			}else if (n > a[middle]) {
				// 在右侧区间中,将left指标右移
				left = middle + 1;
				middle = (left + right) / 2; 
			}else {
				// 在左侧区间中,将right指标左移
				right = middle - 1;
				middle = (left + right) / 2; 
			}
		}
		if (location != -1) {
			System.out.println("位置为" + (location + 1));
		}else {
			System.out.println("数组中没有该元素");
		}
		scanner.close();

三、数组扩容

数组定义后长度固定,可以新建一个数组,迁移原数组数据,并提供更多的空间放入新数据

  • ArrayList的add方法(用于向集合中添加新的元素):ArrayList底层通过数组结构实现,过程与数组扩容步骤类似
  • 代码实现
public static void main(String[] args) {
		// TODO 数组扩容
		/* 用户从控制台不断的录入数据,当数据录入的个数已经超过数组容量时
		可以自动扩容,继续接受元素->ArrayList add()方法源码(10)
		定义一个数组(a),例如长度为5
		定义一个变量,记录用户输入了几个数据,即数组(a)中已经添加了几个元素
		每次用户输入数据时,使用变量判断是否超出了当前数组(a)的长度
		如果超出,定义一个新的数组(b),复制原来数组中的数据到新数组(b)
		将新输入的元素添加到数组(b)中,并将新数组赋值给原数组(a)
		Scanner scanner = new Scanner(System.in);
		控制是否继续输入数据 */ 
		boolean flag = true;
		// 标记数组当前存储元素的个数
		int index = 0;
		while(flag) {
			System.out.println("请输入一个数");
			int number = scanner.nextInt();
			if (index == a.length) {
				extend();
			}
			a[index ++] = number;
			scanner.nextLine();
			System.out.println("是否继续输入y/n");
			String input = scanner.nextLine();
			if ("y".equals(input)) {
				flag = true;
			}else {
				flag = false;
			}
		}
		for (int number : a) {
			System.out.println(number);
		}
		scanner.close();
	}
	
	/**
	 * 将原数组数据保留下来,并扩充空间
	 */
	public static void extend() {
		int[] b = new int[a.length + 1];
		for (int i = 0; i < a.length; i++) {
			b[i] = a[i];
		}
		a = b;
	}

四、数组结构(与链表比较)

  • 数组适合数据的查找,不适合元素的更新,原因:连续的空间
  • 链表不适合数据的查找,适合元素的更新,原因:拆下或插入新节点容易