数据结构:排序篇

最近在学习《极客时间》王争老师的《数据结构与算法之美》,这块知识一直是我比较薄弱的点,之前也没有意识到这块知识的重要性,也在学习的过程中做一些总结,如果想要系统的学习推荐去看一下王争老师的课

排序篇

1、冒泡排序

冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作

	// 冒泡排序,a 表示数组,n 表示数组大小
	public void bubbleSort(int[] a, int n) {
		if (n <= 1)
			return;
		boolean flag;
		for (int i = 0; i < n; ++i) {
			// 提前退出冒泡循环的标志位
			flag = false;
			for (int j = 0; j < n - i - 1; ++j) {
				if (a[j + 1] < a[j]) {
					// 交换
					int tmp = a[j + 1];
					a[j + 1] = a[j];
					a[j] = tmp;
					// 表示有数据交换
					flag = true;
				}
			}
			if (!flag)
				// 没有数据交换,提前退出
				break;
		}
	}

冒泡排序是原地排序算法(空间复杂度O(1)),是稳定的排序算法,最好情况时间复杂度O(n),最坏情况时间复杂度O(n2),平均时间复杂度O(n2)

2、插入排序

我们将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束

	// 插入排序,a 表示数组,n 表示数组大小
	public void insertionSort(int[] a, int n) {
		if (n <= 1)
			return;

		for (int i = 1; i < n; ++i) {
			int value = a[i];
			int j = i - 1;
			// 查找插入的位置
			for (; j >= 0; --j) {
				if (a[j] > value) {
					a[j + 1] = a[j]; // 数据移动
				} else {
					break;
				}
			}
			a[j + 1] = value; // 插入数据
		}
	}

插入排序是原地排序算法,是稳定的排序算法,最好情况时间复杂度O(n),最坏情况时间复杂度O(n2),平均时间复杂度O(n2)

3、快速排序

快排的思想:如果要排序数组中下标从p到r之间的一组数据,我们选择p到r之间的任意一个数据作为pivot(分区点)。我们遍历p到r之间的数据,将小于pivot的放到左边,将大于pivot的放到右边,将pivot放到中间。经过这一步骤之后,数组p到r之间的数据就被分成了三个部分,前面p到q-1之间都是小于pivot的,中间是pivot,后面的q+1到r之间是大于pivot的

根据分治、递归的处理思想,我们可以用递归排序下标从p到q-1之间的数据和下标从q+1到r之间的数据,直到区间缩小为1,就说明所有的数据都有序了

扫描二维码关注公众号,回复: 4771775 查看本文章
public class QuickSort {

	// 快速排序,a是数组,n表示数组的大小
	public static void quickSort(int[] a, int n) {
		quickSortInternally(a, 0, n - 1);
	}

	// 快速排序递归函数,p,r为下标
	private static void quickSortInternally(int[] a, int p, int r) {
		if (p >= r)
			return;

		int q = partition(a, p, r); // 获取分区点
		quickSortInternally(a, p, q - 1);
		quickSortInternally(a, q + 1, r);
	}

	private static int partition(int[] a, int p, int r) {
		int pivot = a[r];
		int i = p;
		for (int j = p; j < r; ++j) {
			if (a[j] < pivot) {
				int tmp = a[i];
				a[i] = a[j];
				a[j] = tmp;
				++i;
			}
		}

		int tmp = a[i];
		a[i] = a[r];
		a[r] = tmp;
		return i;
	}
}

快排是原地排序算法,不是稳定的排序算法,大部分情况下的时间复杂度都是O(nlogn),只有在极端情况下(如果数组中的数据原来已经是有序的了),才会退化到O(n2)

猜你喜欢

转载自blog.csdn.net/qq_40378034/article/details/85758447