快排、归并、并查集

void quick_sort(vector<int>& nums, int l, int r) {
	if (l >= r) return;
	int mid = nums[(l + r) >> 1];
	int i = l - 1, j = r + 1;
	while (i < j) {
		do ++i; while (nums[i] < mid); 
		// 这里一定不可以 = 
		// 因为存在一种情况,我们比较的 target 刚刚好是一个区间的最大值或者最小值
		// 不加 = 号的话,i 和 j 都总是会入侵到对方的区间
		// 加了之后,会存在 
		// 如果target刚好是最大值,i入侵不到
		// 如果target刚好是最大值,j入侵不到
		// 一般情况下:扫描完一次之后
		// i = j + 1 分别入侵了 大于target 和小于target 的区域
		// 或者是 i == j 都入侵了 target
		do --j; while (nums[j] > mid);
		if (i < j) {
			swap(nums[i], nums[j]);
		}
	}
	cout << i << " " << nums[i] << " "<< j << " " << nums[j] << " " << mid << endl;
	quick_sort(nums, l,j);
	quick_sort(nums, j + 1, r);
	// 这里:
	// 可以是 j 和 j + 1
	// 也可以是 i - 1 和 i
	// 因为在最后,i 是向左进入了他不应该进入的地区:nums[i] >= mid
	// j 是向左进入了 他不该进入的地区, 所以是: nums[j] <= mid
	// 所以 j 需要被左侧包含进去,i需要被右侧包含进去
	/*所有的可能:
		按照顺序排好了:
		find 6
		0 1 2 3 4
		5 8 9
		i   j
		j i

		没按照顺序排好了:
		find 8
		0 1 2 3 4
		5 9 8
		i   j
		i j
		5 8 9
		i j
		j i*/
}

void quick_sort1(vector<int>& nums, int l, int r) {
	if (l >= r) return;
	int temp = nums[l];
	int i = l, j = r;
	while (i < j) {
		while (i < j && nums[j] > temp) --j;
		if (i < j) nums[i++] = nums[j];
		while (i < j && nums[i] < temp) ++i;
		if (i < j) nums[j--] = nums[i];
	}
	nums[j] = temp; 
	cout << i << " " << nums[i] << " " << j << " " << nums[j] << " " << temp << endl;
	quick_sort1(nums, l, j);
	quick_sort1(nums, j + 1, r);
	// 这个和第一个就不同
	// 这个快排的终止条件一定是 i == j
	// 而且是把 目标值放在了 i == j的位置上
	// 这个也能像第一种快排方法一样理解
	// 当快排序完成时:中间会有一条分界线 左边<= target 右边>= target
	// 但是第二种快排,当i和j有一个入侵到对方时,另一个就不会入侵了,最多走到i == j的位置
	// 而且这时把 target 放到了这个位置
}

上一篇:HCIA---静态综合实验


下一篇:PTA 1002题解