Java数据结构——排序算法总结

1. 关键术语总结

1. 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
2. 不稳定 :如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面。
3. 内排序 :所有排序操作都在内存中完成。
4. 外排序 :由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行。
5. 时间复杂度 : 一个算法执行所耗费的时间。
6. 空间复杂度 :运行完一个程序所需内存的大小。

2. 排序算法比较表


在这里插入图片描述


3. 排序算法分类


在这里插入图片描述


4. 类Sort

package sort;

public class Sort {

	/**
	 * 直接插入排序
	 * 
	 * @param arrs 待排序数组
	 */
	// TODO
	public void insertionSort(int[] arrs) {
		int n = arrs.length;

		for (int i = 0; i < n; i++) {

			// 1. 寻找元素 arrs[i] 合适的插入位置
			for (int j = i; j > 0; j--) {

				// 2. 找到合适位置就交换
				if (arrs[j] < arrs[j - 1]) // 决定升降序
					swap(arrs, j, j - 1);
				else
					break;
			}
		}
	} // insertionSort

	/**
	 * 数组两个位置交换
	 * 
	 * @param arrs
	 * @param i
	 * @param j
	 */
	private void swap(int[] arrs, int i, int j) {
		int temp = arrs[i];
		arrs[i] = arrs[j];
		arrs[j] = temp;
	} // swap

	/**
	 * 测试直接插入排序
	 */
	public static void testOfInsertionSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		sort.insertionSort(arrs);
		for (int i = 0; i < arrs.length; i++) {
			System.out.print(arrs[i]);
			System.out.print(" ");
		}
	}

	/**
	 * 希尔排序
	 * 
	 * @param arrs
	 */
	// TODO
	public void shellSort(int[] arrs) {
		int n = arrs.length;

		// 1. 以n/2为间隔(增量),直到增量为1
		for (int step = n / 2; step >= 1; step /= 2) {

			// 2. 直接插入排序
			for (int i = step; i < n; i++) {
				// j每次递减是减少step那么多
				for (int j = i; j > step - 1; j -= step) {
					if (arrs[j - step] > arrs[j])
						swap(arrs, j - step, j);
					else
						break;
				}
			}
		}
	} // shellSort

	/**
	 * 测试希尔排序
	 */
	public static void testOfShellSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		sort.shellSort(arrs);
		for (int i = 0; i < arrs.length; i++) {
			System.out.print(arrs[i]);
			System.out.print(" ");
		}
	}

	/**
	 * 冒泡排序
	 * 
	 * @param arrs
	 */
	// TODO
	public void bubbleSort(int[] arrs) {
		int n = arrs.length;

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n - 1 - i; j++) {
				if (arrs[j] > arrs[j + 1]) {
					swap(arrs, j, j + 1);
				}
			}
		}
	} // bubbleSort

	public void BubbleSort(int[] arrs) {
		int n = arrs.length;

		for (int i = 1; i < n; i++) {
			boolean flag = true;

			for (int j = 0; j < n - i; j++) {
				if (arrs[j] > arrs[j + 1]) {
					swap(arrs, j, j + 1);
					flag = false;
				}
			}

			if (flag) {
				break;
			}
		}
	} // BubbleSort

	/**
	 * 测试冒泡排序
	 */
	public static void testOfBubbleSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		// sort.bubbleSort(arrs);
		sort.BubbleSort(arrs);
		for (int i = 0; i < arrs.length; i++) {
			System.out.print(arrs[i]);
			System.out.print(" ");
		}
	}

	/**
	 * 快速排序
	 * 
	 * @param arrs
	 * @param leftIndex
	 * @param rightIndex
	 */
	// TODO
	public void quickSort(int[] arrs, int leftIndex, int rightIndex) {
		// 1. 没有或只有1个元素
		if (leftIndex >= rightIndex) {
			return;
		}

		// 2. 设置基准:pivotkey
		int left = leftIndex;
		int right = rightIndex;
		int key = arrs[left];

		// 3. 分区
		while (left < right) {
			// 3.1 比基准大
			while (right > left && arrs[right] >= key) {
				// 从右往左扫描,找到第一个比基准值小的元素
				right--;
			}
			// 找到这种元素将arr[right]放入arr[left]中
			arrs[left] = arrs[right];

			// 3.2 比基准小
			while (left < right && arrs[left] <= key) {
				// 从左往右扫描,找到第一个比基准值大的元素
				left++;
			}
			// 找到这种元素将arr[left]放入arr[right]中
			arrs[right] = arrs[left];
		}

		// 4. 基准在两部分中间(low = high)
		arrs[left] = key;

		// 5. 对两部分递归排序
		quickSort(arrs, leftIndex, left - 1);
		quickSort(arrs, right + 1, rightIndex);
	} // quickSort

	/**
	 * 测试快速排序
	 */
	public static void testOfQuickSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		sort.quickSort(arrs, 0, arrs.length - 1);
		for (int i = 0; i < arrs.length; i++) {
			System.out.print(arrs[i]);
			System.out.print(" ");
		}
	}

	/**
	 * 选择排序
	 * 
	 * @param arrs
	 */
	// TODO
	public void selectionSort(int[] arrs) {
		int n = arrs.length;
		int min;

		// 总共要经过 N-1 轮比较
		for (int i = 0; i < n - 1; i++) {
			min = i;

			// 1. 每轮需要比较的次数 N-i-1
			for (int j = i + 1; j < n; j++) {
				if (arrs[j] < arrs[min]) {
					min = j;
				}
			}

			// 2. 将找到的最小值和i位置所在的值进行交换
			if (i != min)
				swap(arrs, i, min);
		}
	} // selectionSort

	/**
	 * 测试选择排序
	 */
	public static void testOfSelectionSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		sort.selectionSort(arrs);
		for (int i = 0; i < arrs.length; i++) {
			System.out.print(arrs[i]);
			System.out.print(" ");
		}
	}

	/**
	 * 堆排序
	 * 
	 * @param arrs
	 */
	// TODO
	public void heapSort(int[] arrs) {
		int n = arrs.length;

		// 1. 构建大顶堆——升序
		for (int i = n / 2 - 1; i >= 0; i--) {
			adjustHeap(arrs, i, n);
		}

		// 2. 堆排序
		for (int i = n - 1; i > 0; i--) {
			// 2.1 将堆顶元素与末尾元素进行交换
			swap(arrs, 0, i);
			// 2.2 重新对堆进行调整
			adjustHeap(arrs, 0, i);
		}
	} // heapSort

	/**
	 * 调整堆
	 * 
	 * @param arrs
	 * @param index
	 * @param length
	 */
	private void adjustHeap(int[] arrs, int index, int length) {

		// 1. 大堆顶,根节点是最大的
		int root = arrs[index];

		// 2. 构造大堆顶
		for (int i = 2 * index + 1; i < length; i = i * 2 + 1) {

			// 2.1 左右节点比较
			if (arrs[i] < arrs[i + 1] && (i + 1) < length) {
				i++;
			}

			// 2.2 父子节点比较
			if (arrs[i] > root) {
				arrs[index] = arrs[i];
				index = i;
			} else {
				break;
			}
		} // end for

		// 3. 把根节点放在该到的位置
		arrs[index] = root;
	}

	/**
	 * 测试堆排序
	 */
	public static void testOfHeapSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		sort.heapSort(arrs);
		for (int i = 0; i < arrs.length; i++) {
			System.out.print(arrs[i]);
			System.out.print(" ");
		}
	}

	/**
	 * 归并排序
	 * 
	 * 自下而上的迭代
	 * 
	 * @param arrs
	 * @return
	 */
	// TODO
	public int[] mergeSort(int[] arrs) {
		int n = arrs.length;
		int mid = n / 2;
		int[] left = new int[mid];
		int[] right = new int[n - mid];

		if (n < 2) {
			return arrs;
		}
		left = copyOfRange(arrs, 0, mid);
		right = copyOfRange(arrs, mid, n);

		// 迭代
		return merge(mergeSort(left), mergeSort(right));
	} // mergeSort

	/**
	 * 复制函数
	 * 
	 * 下面是 System.arrayCopy的源代码声明 : public static void arraycopy(Object src, int
	 * srcPos, Object dest, int destPos, int length) 代码解释: Object src : 原数组 int
	 * srcPos : 从元数据的起始位置开始 Object dest : 目标数组 int destPos : 目标数组的开始起始位置 int length
	 * : 要copy的数组的长度
	 * 
	 * @param arrs
	 * @param start
	 * @param end
	 * @return
	 */
	private int[] copyOfRange(int[] original, int start, int end) {
		int newLength = end - start;
		if (newLength < 0)
			throw new IllegalArgumentException(start + " > " + end);

		int[] copy = new int[newLength];
		System.arraycopy(original, start, copy, 0, Math.min(original.length - start, newLength));
		return copy;
	}

	/**
	 * 归并
	 * 
	 * @param left
	 * @param right
	 * @return
	 */
	private int[] merge(int[] left, int[] right) {
		int[] result = new int[left.length + right.length];
		int i = 0;

		// 1. left和right
		while (left.length > 0 && right.length > 0) {
			if (left[0] < right[0]) {
				result[i++] = left[0];
				left = copyOfRange(left, 1, left.length); // 前移
			} else {
				result[i++] = right[0];
				right = copyOfRange(right, 1, right.length);
			}
		}

		// 2. left
		while (left.length > 0) {
			result[i++] = left[0];
			left = copyOfRange(left, 1, left.length);
		}

		// 3. right
		while (right.length > 0) {
			result[i++] = right[0];
			right = copyOfRange(right, 1, right.length);
		}

		return result;
	}

	/**
	 * 测试归并排序
	 */
	public static void testOfMergeSort() {
		int[] arrs = { 5, 11, 1, 0, -1, 15, 20, 100, -99 };
		Sort sort = new Sort();

		int[] result = sort.mergeSort(arrs);
		for (int i = 0; i < result.length; i++) {
			System.out.print(result[i]);
			System.out.print(" ");
		}
	}

	public static void main(String[] args) {
		System.out.println("\r\n直接插入排序:");
		testOfInsertionSort();
		System.out.println("\r\n希尔排序:");
		testOfShellSort();
		System.out.println("\r\n冒泡排序:");
		testOfBubbleSort();
		System.out.println("\r\n快速排序:");
		testOfQuickSort();
		System.out.println("\r\n选择排序:");
		testOfSelectionSort();
		System.out.println("\r\n堆排序:");
		testOfHeapSort();
		System.out.println("\r\n归并排序:");
		testOfMergeSort();
	}
}
  • 输出样例:

直接插入排序:
-99 -1 0 1 5 11 15 20 100 
希尔排序:
-99 -1 0 1 5 11 15 20 100 
冒泡排序:
-99 -1 0 1 5 11 15 20 100 
快速排序:
-99 -1 0 1 5 11 15 20 100 
选择排序:
-99 -1 0 1 5 11 15 20 100 
堆排序:
-99 -1 0 1 5 11 15 20 100 
归并排序:
-99 -1 0 1 5 11 15 20 100 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姜满月

鼓励,鼓励,更加努力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值