The sixth sort -- quick sort

void quickSort(vector<int>& v, int left, int right) {
	if (left >= right)return;
	
	int pirot = v[right];
	int leftField = left;
	int rightField = right;

	for (; leftField < rightField; leftField++) {
		if (v[leftField] <= pirot)continue;
		else {
			rightField--;
			swap(v, leftField, rightField);
			leftField--;//Because when I go out, I will + +.
		}
	}
	swap(v, leftField, right);
	quickSort(v, left, leftField - 1);
	quickSort(v, leftField + 1, right);
}

The idea of quick sort is to find an axis, partition the data, and then recurse!

When it comes to zoning, we should also pay attention to the opening and closing interval of the boundary.  

void quickSort(vector<int>& v, int left, int right) {
	if (left >= right)return;
	int leftZone = left;
	int rightZone = right - 1;//Here, let the two pointers of the left and right regions be open intervals, which is conducive to traversal
	int pirot = v[right];
	while (leftZone <= rightZone) {
		if (v[leftZone] <= pirot) {
			leftZone++;
		}
		else {
			swap(v, leftZone, rightZone);
			rightZone--;
		}
		if (leftZone <= rightZone) {
			if (v[rightZone] >= pirot) {
				rightZone--;
			}
			else {
				swap(v, leftZone, rightZone);
				leftZone++;
			}
		}
		else {
			break;
		}
	}
	swap(v, leftZone, right);//You need to change the final axis node with the large one, and then you don't need to control the axis when recursing
	quickSort(v, left, leftZone - 1);
	quickSort(v, leftZone + 1, right);
}

This implementation is an upgraded version of the one above, that is, while traversing, do it on the left and on the right, so that the two go to the middle at the same time.

Pay attention to the recursive algorithm and don't forget to write the recursive base. Otherwise, you always think it's the next thing when the array crosses the boundary. Without the recursive base, the array can't cross the boundary!!

void quickSort(vector<int>& v, int left, int right) {
	if (left >= right)return;
	int leftZone = left;
	int rightZone = right - 1;
	int pirot = v[right];
	while (leftZone <= rightZone) {
		
		while (leftZone <= right && v[leftZone] < pirot)leftZone++;
		while (rightZone >= left && v[rightZone] > pirot)rightZone--;//Think about the following equal sign
		if (leftZone < rightZone)swap(v, leftZone++, rightZone--);
	}
	swap(v, leftZone, right);
	quickSort(v, leftZone + 1, right);
	quickSort(v, left, leftZone - 1);
}

  First of all, this is an endless waste solution. After reading through the code, we found the reason, that is, there should be an else behind the if in the while, that is, they have gone too far and just break directly!

void quickSort(vector<int>& v, int left, int right) {
	if (left >= right)return;
	int leftZone = left;
	int rightZone = right - 1;
	int pirot = v[right];
	while (leftZone <= rightZone) {
		
		while (leftZone <= right && v[leftZone] < pirot)leftZone++;
		while (rightZone >= left && v[rightZone] > pirot)rightZone--;//Think about the following equal sign
		if (leftZone <= rightZone) { swap(v, leftZone++, rightZone--); }
		else { break; }
		
	}
	swap(v, leftZone, right);
	quickSort(v, leftZone + 1, right);
	quickSort(v, left, leftZone - 1);
}

In fact, for the fast row, the number equal to the axis can be placed on either side, or even on both sides, because both sides are symmetrical. So it doesn't matter. In addition, we play recursion next. As long as the left is less than or equal to the right, it must be right after the order is finally arranged.

void quickSort(vector<int>& v, int leftBound, int rightBound) {
	if (leftBound >= rightBound)return;
	//Note that the recursive base here is the same as before
	int left = leftBound + 1;
	int right = rightBound - 1;//right all three are open intervals
	int mid = left;
	int pirotSmall = min(v[leftBound], v[rightBound]);
	int pirotBig = max(v[leftBound], v[rightBound]);
	cout << "small and big :" << pirotSmall << "  " << pirotBig << endl;
	while (mid <= right) {
		if (v[mid] <= pirotSmall) {
			swap(v, mid, left);
			mid++;
			left++;
		}
		else if (v[mid] >= pirotBig) {
			swap(v, right, mid);
			right--;
		}
		else {
			mid++;
		}
	}
	cout << "before swap:" << endl;
	print(v);
	swap(v, left - 1, leftBound);
	swap(v, mid, rightBound);
	cout << "after swap" << endl;
	print(v);
	quickSort(v, leftBound, left - 2);
	quickSort(v, left, mid - 1);
	quickSort(v, mid + 1, rightBound);
}

  There is a BUG in the above writing, that is, when recursion is only two elements, and when it is in reverse order, the recursive circle is still in reverse order!!!

Why is there such a problem?

You have a problem that has been ignored, that is, your left and right endpoints. Your two axes are selected according to the size, but you have not adjusted the size of the last two endpoints, that is, the left endpoint may be larger than the right endpoint!!!

void quickSort(vector<int>& v, int leftBound, int rightBound) {
	if (leftBound >= rightBound)return;
	//Note that the recursive base here is the same as before
	int left = leftBound + 1;
	int right = rightBound - 1;//right all three are open intervals
	int mid = left;
	int pirotSmall = min(v[leftBound], v[rightBound]);
	int pirotBig = max(v[leftBound], v[rightBound]);
	if (v[leftBound] > v[rightBound])swap(v, leftBound, rightBound);
	while (mid <= right) {
		if (v[mid] <= pirotSmall) {
			swap(v, mid, left);
			mid++;
			left++;
		}
		else if (v[mid] >= pirotBig) {
			swap(v, right, mid);
			right--;
		}
		else {
			mid++;
		}
	}

	swap(v, left - 1, leftBound);
	swap(v, mid, rightBound);
	quickSort(v, leftBound, left - 2);
	quickSort(v, left, mid - 1);
	quickSort(v, mid + 1, rightBound);
}

Sure enough, it is the problem of the left and right boundaries mentioned above. This is directly passed!!!

Tags: Algorithm leetcode Dynamic Programming

Posted on Sun, 28 Nov 2021 08:58:31 -0500 by retoknaak