--- tags: data structure and algorithm --- # 排序演算法 --- ## 以比較為基礎的排序演算法 ### Insertion Sort 1. 將待排序的資料分為已排序完成與未排序完成兩個子集合。 2. 在排序過程中,由未排序完成的子集合中任取一個元素,插入已排序完成的子集合中。 3. 重複步驟 2 直到未排序完成的子集合成為空集合為止。 在排序小量資料時, insertion sort 是個有效率的排序演算法。 當輸入資料已陣列儲存時, insertion sort 可在原輸入陣列中完成排序。所以, insertion sort 的空間複雜度為 $O(1)$ 。 #### C++ Code ```cpp= class Solution { public: vector<int> sortArray(vector<int>& nums) { for (int j = 1; j < nums.size(); ++j) { // nums[0..i] is the sorted subarray. // nums[j..len-1] is the unsorted subarray. int i = j - 1; int key = nums[j]; while (i >= 0 && nums[i] > key) { nums[i + 1] = nums[i]; --i; } // case 1: i < 0 // case 2: nums[i] <= key if (i < 0) { // The original subarray, nums[0..i], was sorted and // key is less than nums[0]. // The original sorted subarray, nums[0..i], has been // moved to nums[1..j]. // nums[0] is the right position for key to make // nums[0..j] the new sorted subarray. nums[i + 1] = key; } else { // Now, nums[i] <= key and we have move the original // subarray, nums[i+1 .. j-1], to nums[i+1 .. j]. // nums[i+1] is the right position for key to make // the new sorted subarray, nums[0..j] nums[i + 1] = key; } } return nums; } }; ``` #### Time Complexity * Worst Case (輸入資料反向排序) $O(n^{2})$ $n$ is the length of `nums`. * Average Case $O(n^{2})$ * Best Case (輸入資料已排序完成) $O(n)$ #### Space Complexity $O(1)$ ### Merge Sort #### C++ Code ```cpp= class Solution { public: vector<int> sortArray(vector<int> &nums) { mergeSort(nums, 0, nums.size() - 1); return nums; } private: void mergeSort(vector<int> &nums, int left, int right) { if (left < right) { int middle = left + (right - left) / 2; mergeSort(nums, left, middle); mergeSort(nums, middle + 1, right); merge(nums, left, middle, right); } } void merge(vector<int> &nums, int left, int middle, int right) { vector<int> numsLeft(middle - left + 1), numsRight(right - middle); for (int i = 0; i < numsLeft.size(); ++i) { numsLeft[i] = nums[left + i]; } for (int i = 0; i < numsRight.size(); ++i) { numsRight[i] = nums[middle + 1 + i]; } numsLeft.push_back(INT_MAX); numsRight.push_back(INT_MAX); int leftIdx = 0, rightIdx = 0; for (int i = left; i <= right; ++i) { if (numsLeft[leftIdx] < numsRight[rightIdx]) { nums[i] = numsLeft[leftIdx++]; } else { nums[i] = numsRight[rightIdx++]; } } } }; ``` #### Time Complexity $O(nlogn)$ $n$ is the length of `nums`. #### Space Complexity $O(n)$ ### Quick Sort #### C++ Code ```cpp= ``` #### Time Complexity #### Space Complexity ### Heap Sort #### C++ Code ```cpp= class Solution { public: vector<int> sortArray(vector<int> &nums) { buildHeap(nums); heapSort(nums); return nums; } private: void buildHeap(vector<int> &nums) { for (int parentIdx = (nums.size() >> 1) - 1; parentIdx >= 0; --parentIdx) { maxHeapify(nums, parentIdx, nums.size()); } } void maxHeapify(vector<int> &nums, int rootIdx, int len) { int maxIdx = rootIdx, leftIdx = (rootIdx << 1) + 1, rightIdx = (rootIdx << 1) + 2; if (leftIdx < len && nums[maxIdx] < nums[leftIdx]) { maxIdx = leftIdx; } if (rightIdx < len && nums[maxIdx] < nums[rightIdx]) { maxIdx = rightIdx; } if (maxIdx != rootIdx) { swap(nums[maxIdx], nums[rootIdx]); maxHeapify(nums, maxIdx, len); } } void heapSort(vector<int> &maxHeap) { for (int i = maxHeap.size() - 1; i >= 0; --i) { swap(maxHeap[0], maxHeap[i]); maxHeapify(maxHeap, 0, i); } } }; ``` #### Time Complexity * Best Case: $O(n)$ $n$ is the length of `num`. This is the runtime when everything in the input is identical. * Worst Case: $O(nlogn)$ $n$ is the length of `num`. * Average Case: $O(nlogn)$ $n$ is the length of `num`. #### Space Complexity $O(1)$ ## 不是以比較為基礎的排序演算法