The main reason why I write this blog is that for fast platoon, recursive implementation is so ingrained in our minds that our conditioned reflection is fast platoon. Is there any non recursive implementation? I haven't seen it before. It's also to deepen my understanding of recursion~
I won't talk about the principle of quick sorting here. The implementation is the divide and conquer method. For more details, please refer to another blog of mine Insert class sort . Also welcome to follow my blog ~ ~ HH
Recursively implemented Code:
#include <iostream> #include <stack> #include<vector> using namespace std; class Solution { public: void quickSort(vector<int>& nums, int left, int right) { if (left < right) { int mid = merge(nums, left, right); quickSort(nums, left, mid - 1); quickSort(nums, mid + 1, right); } } int merge(vector<int>& nums, int left, int right) { while (left < right) { while (left < right && nums[left] < nums[right]) --right; //Scan right to left if (left < right) { swap(nums[left], nums[right]); } while (left < right && nums[left] < nums[right]) ++left; //Scan left to right if (left < right) { swap(nums[left], nums[right]); } } return left; //Location of current target } }; int main() { vector<int> nums = { 2, 6, 1, 7, 8, 3, 5, 10, 9, 4 }; Solution().quickSort(nums, 0, nums.size() - 1); return 0; }
In fact, the most important part of analyzing the implementation of the above recursion is not in the recursion part, but in merge. The function is to ensure that the element values on the left are less than or equal to the "target stake", and the element values on the right are greater than the "target stake". So after every merge, the target pile will reach its target position. So the key of non recursive implementation is how to merge the left sequence and the right sequence respectively. In fact, we only need to use the stack to save the start and end positions of the left sequence and the right sequence, and then take the sequence at the top of the stack for merge each time. The reason why stack is used instead of queue is that the nature of stack is first in, first out, and recursion is actually the compiler using stack to save context switching information.
To sum up, the non recursive algorithm is as follows:
#include <iostream> #include <stack> #include<vector> using namespace std; class Solution { public: void quickSort(vector<int>& nums, int left, int right) { stack<pair<int, int>> curChangePos; //Save the start and end positions of the current sequence to merge curChangePos.push({ left, right }); while (!curChangePos.empty()) { pair<int, int> curPos = curChangePos.top(); curChangePos.pop(); if (curPos.first < curPos.second) { int mid = merge(nums, curPos.first, curPos.second); curChangePos.push({ curPos.first, mid-1 }); //Sequence on the left curChangePos.push({ mid + 1, curPos.second }); //Sequence on the right } } } int merge(vector<int>& nums, int left, int right) { while (left < right) { while (left < right && nums[left] < nums[right]) --right; //Scan right to left if (left < right) { swap(nums[left], nums[right]); } while (left < right && nums[left] < nums[right]) ++left; //Scan left to right if (left < right) { swap(nums[left], nums[right]); } } return left; //Location of current target } }; int main() { vector<int> nums = { 2, 6, 1, 7, 8, 3, 5, 10, 9, 4 }; Solution().quickSort(nums, 0, nums.size() - 1); return 0; }