快速排序

快速排序原理

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

  • 首先设定一个分界值,通过该分界值将数组分成左右两部分。
  • 将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
  • 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
  • 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

举例分析

在这里插入图片描述
选取上述数组的第一个元素6作为基准元,左游标是 i 哨兵,右游标是 j 哨兵,它们遵循的规则如下:
一、左游标向右扫描, 跨过所有小于基准元素的数组元素, 直到遇到一个大于或等于基准元素的数组元素, 在那个位置停下。二、右游标向左扫描, 跨过所有大于基准元素的数组元素, 直到遇到一个小于或等于基准元素的数组元素,在那个位置停下。

第一步:哨兵 j 先开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵 j 先开始出动,哨兵 j 逐步向左挪动,直到找到一个小于 6 的元素停下来。接下来哨兵 i 再逐步向右挪动,直到找到一个大于 6 的元素停下来。最后哨兵 i 停在了数字 7 面前,哨兵 j 停在了数字 5 面前。
在这里插入图片描述
到此第一次交换结束,接着哨兵 j 继续向左移动,它发现 4 比基准数 6 要小,那么在数字4面前停下来。哨兵 i 也接着向右移动,然后在数字 9 面前停下来,然后哨兵 i 和 哨兵 j 再次进行交换。
在这里插入图片描述
第二次交换结束,哨兵 j 继续向左移动,然后在数字 3 面前停下来;哨兵 i 继续向右移动,但是它发现和哨兵 j 相遇了。那么此时说明探测结束,将数字 3 和基准数字 6 进行交换。
在这里插入图片描述
到此第一趟探测真正结束,此时以基准点6为分界线,左边的数组元素都小于等于6,右边的数组元素都大于等于6。左边序列为3,1,2,5,4。右边序列为9,7,10,8。此时对于左边序列而言,以数字3为基准元素,重复上面的探测,探测完毕之后的序列为2,1,3,5,4。对于右边序列而言,以数字9为基准元素,也重复上面的探测,一步一步的划分最后排序完全结束。

复杂度

时间复杂度:最好情况(待排序列接近无序)时间复杂度为O(nlog2n),最坏情况(待排序列接近有序)时间复杂度为O(n2),平均时间复杂度为O(nlog2n)。

代码实现

public void quickSort(int[] arr, int left, int right) {

		// 当左边大于于右边的时候直接返回
		if (right <= left)
			return;
		int key = arr[left];// 进行划分的值
		int i = left, j = right;//
		while (i < j) {

			// 在右边找到第一个比key小的值
			while (i < j && arr[j] >= key) {
				j--;
			}
			// 在左边找到第一个比key大的值
			while (i < j && arr[i] <= key) {
				i++;
			}
			if (i < j) {
				exch(arr, i, j);
			}

		}
		// 这个时候i和j已经是相等的了,j右边的元素都不小于key,所以把key和j所对应的元素直接交换位置就行了,接下来就是将key放到相应的位置。
		exch(arr, left, j);
		quickSort(arr, left, i - 1);
		quickSort(arr, i + 1, right);

	}

	public void exch(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

发布了28 篇原创文章 · 获赞 8 · 访问量 8139
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章