数据结构之排序二(希尔、归并、快速)

目录

希尔排序

归并排序

快速排序



一、希尔排序

      希尔排序又叫“缩小增量”,(是不稳定的排序方法)。

      先将整个数组 k=(n/2)分。把k数作为“增量”。然后将所有距离为k的倍数的数分到同一组。一共分为k组。然后对每一组进行插入排序。再进行 (k/2),重复上面。直到排序成功
      时间复杂度:O(n的1.3次方)
在这里插入图片描述

  1. 首先选择增量为10/2 = 5,所以按照增量为5,划分为5组。[8,3]、[9,5]、[1,4]、[7,6]、[2,0]
  2. 对上面5组进行插入排序,变为:3,5,1,6,0,8,9,4,7,2。
  3. 下一步缩小增量,5/2 = 2,然后分为两组[3,1,0,9,7]、[5,6,8,2,4]。
  4. 再对上面的两组进行插入排序0,1,3,7,9,2,4,5,6,8
  5. 重复步骤,一直到排序完成。
int[] arr = new int[] {8,9,1,7,2,3,5,4,6,0};

		// 拿到每轮的步长,步长的计算方法就是用数组长度除2。
		// 下一轮的步长就是d/=2。
		for (int d = arr.length / 2; d > 0; d /= 2) {

			// 拿到步长后,就要遍历每一组元素。进行插入比较了
			// 就是从步长位置,遍历后面的元素。
			for (int i = d; i < arr.length; i++) {

				// 因为,要比较的元素不是从步长开始的。
				// 要从第一号元素开始的。所以j = i - d;
				/*
				 * 因为插入排序,当前和后面的比较后,换位。还要和前面的比较的, 所以,换位后的下一步是和前面的进行比较的。所以j-=d;
				 */
				for (int j = i - d; j >= 0; j -= d) {

					// 比较换位
					if (arr[j] > arr[j + d]) {

						int temp = arr[j];
						arr[j] = arr[j + d];
						arr[j + d] = temp;
					}
				}
			}
		}
		
		System.out.println(Arrays.toString(arr));

返回顶部

二、归并排序

      将两个或两个以上的有序文件合并成为一个新的有序文件。

      将n个记录无序的文件看成是由n个长度为1的有序子文件组成的文件,然后进行两两归并。得到n/2个长度为2或1的有序文件、再重复。知道得到n个记录的有序文件为止。称为 两路归并排序。

      有两种归并排序的方式:从上往下,从下往上。

在这里插入图片描述

  1. 先把数组进行对半分解,一直分到只有一个元素。
  2. 然后,对单个元素的数组进行合并。一直到合并成整个数组
public static void main(String[] args) {
		
		int[] arr = { 10, 20, 30, 50, 40, 60};
		int[] tmp = new int[arr.length]; // 新建一个临时数组存放
		
		mergeSort(arr, 0, arr.length - 1, tmp);
		
		System.out.println(Arrays.toString(arr));
	}

	public static void merge(int[] arr, int low, int mid, int high, int[] tmp) {
		int i = 0;
		int j = low, k = mid + 1; // 左边序列和右边序列起始索引
		while (j <= mid && k <= high) {
			if (arr[j] < arr[k]) {
				tmp[i++] = arr[j++];
			} else {
				tmp[i++] = arr[k++];
			}
		}
		// 若左边序列还有剩余,则将其全部拷贝进tmp[]中
		while (j <= mid) {
			tmp[i++] = arr[j++];
		}

		while (k <= high) {
			tmp[i++] = arr[k++];
		}

		for (int t = 0; t < i; t++) {// 存储排序后的顺序数组。
			arr[low + t] = tmp[t];
		}
	}

	public static void mergeSort(int[] arr, int low, int high, int[] tmp) {
		
		if (low < high) {
			int mid = (low + high) / 2;
			mergeSort(arr, low, mid, tmp); // 对左边序列进行归并排序
			mergeSort(arr, mid + 1, high, tmp); // 对右边序列进行归并排序
			merge(arr, low, mid, high, tmp); // 合并两个有序序列
		}
	}

返回顶部

三、快速排序

       一趟排序将数组分成独立的两部分。分为前半区和后半区。前半区的记录均不大于后半区记录的关键字。然后,再分别对这两部分进行快速排序。

在这里插入图片描述

  1. 首先拿数组的第一个数出来作为基准数x = 30,记第一位为i = 0,
  2. 先从数组最后一位数向前查找,找到x > arr[ j ],然后把arr[ i ] = arr[ j ],
  3. 赋值完之后,然后,从i位起向后比较,找到x < arr[ i ],然后把arr[ j ] = arr[ i ];
  4. 然后一直重复,到最后,i = j,把x 赋值到最后的索引位置。
public static void main(String[] args) {

		int[] arr = { 10, 20, 30, 50, 40, 60 };

		quickSort(arr, 0, arr.length - 1);

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

	private static void quickSort(int[] arr, int low, int high) {// 递归比那里查询比较

		if (low < high) {
			// 找寻基准数据的正确索引
			int index = getIndex(arr, low, high);

			// 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序
			quickSort(arr, 0, index - 1);
			quickSort(arr, index + 1, high);
		}

	}

	private static int getIndex(int[] arr, int low, int high) {
		// 基准数据
		int tmp = arr[low];
		while (low < high) {
			// 当队尾的元素大于等于基准数据时,向前挪动high指针
			while (low < high && arr[high] >= tmp) {
				high--;
			}
			// 如果队尾元素小于tmp了,需要将其赋值给low
			arr[low] = arr[high];
			// 当队首元素小于等于tmp时,向前挪动low指针
			while (low < high && arr[low] <= tmp) {
				low++;
			}
			// 当队首元素大于tmp时,需要将其赋值给high
			arr[high] = arr[low];

		}
		// 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置
		// 由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要将tmp赋值给arr[low]
		arr[low] = tmp;
		return low; // 返回tmp的正确位置
	}

返回顶部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值