赞
踩
归并排序是一种分治算法,由约翰·冯·诺伊曼在1945年发明。它的工作原理是将未排序的列表划分为n个子列表,每个子列表包含一个元素(包含一个元素的列表被认为是有序的),然后重复合并子列表以生成新的有序子列表,直到只剩下一个子列表。
function mergeSort(list) if length(list) <= 1 return list mid <- length(list) / 2 left <- mergeSort(list[0...mid]) right <- mergeSort(list[mid+1...end]) return merge(left, right) end function function merge(left, right) result <- empty list while left and right are not empty if first(left) <= first(right) append first(left) to result remove first element from left else append first(right) to result remove first element from right end if end while append remaining elements of left and right (if any) to result return result end function
归并排序是一种高效的排序算法,其优缺点如下:
总体而言,归并排序是一种高效的通用排序算法,特别适合需要稳定排序和大量数据的情况。然而,如果内存使用是一个关键因素,或者数据集非常小,可能需要考虑其他排序算法。
归并排序是一种高效的通用排序算法,由于其稳定性和(O(n log n))的时间复杂度,它在多种应用场景中都非常适用。以下是一些归并排序的常见应用场景:
尽管归并排序在许多场景中都非常适用,但它也有一些局限性。例如,归并排序需要额外的存储空间,这在内存受限的环境中可能是一个问题。此外,对于小数据集,归并排序可能不如其他简单的排序算法(如插入排序)效率高,因为归并排序的常数因子较大。因此,在实际应用中,通常会根据具体的需求和数据特性来选择最合适的排序算法。
归并排序的时间复杂度在最好情况、最坏情况和平均情况下的表现如下
最好情况发生在输入数组已经是有序的情况下。在这种情况下,每个子数组都是有序的,所以合并操作会非常快,只需要一次比较就可以将两个子数组合并成一个有序数组。但是,分割过程仍然需要执行 (log(n)) 次,因为我们需要将整个数组分成两个有序的子数组。因此,最好情况下的时间复杂度是 (O(n))。
最坏情况发生在输入数组是完全逆序的情况下。在这种情况下,每次合并操作都需要比较和移动所有的元素,因为我们需要将最大的元素移动到数组的末尾。因此,最坏情况下的时间复杂度是 (O(nlog(n)))。
平均情况下,输入数组的元素是随机排列的。在这种情况下,归并排序的时间复杂度仍然是 (O(nlog(n)))。这是因为尽管某些合并操作可能比最好情况下的时间复杂度高,但平均来看,每个元素仍然只需要比较和移动 (log(n)) 次。
小结:
归并排序的时间复杂度不受输入数据初始顺序的影响,因为它总是需要进行 (log(n)) 次分割,并且每次合并操作的复杂度是 (O(n))。因此,归并排序是一个稳定的排序算法,其性能在各种情况下都是可预测的。
归并排序的时间复杂度主要由两部分组成:分割和合并。
综合以上两点,归并排序的时间复杂度是 (O(n log n))。这是因为分割过程的时间复杂度是 O(log n),而合并过程的时间复杂度是 (O(n)),所以总的时间复杂度是 (O(n log n))。
归并排序的空间复杂度主要由合并过程中的临时数组决定。
因此,归并排序的空间复杂度是 (O(n)),因为它需要一个额外的数组来存储合并过程中的临时结果。
我们可以通过数学归纳法来证明归并排序的时间复杂度是 (O(n log n))。
基础情况:当数组大小为 1 时,不需要排序,时间复杂度为 O(1)。
归纳假设:假设对于大小为 k 的数组,归并排序的时间复杂度是 O(k log k)。
归纳步骤:对于大小为 2k 的数组,我们将其分成两个大小为 k 的子数组,分别对它们进行排序,然后合并。根据归纳假设,每个子数组的排序时间是 O(k log k),合并时间是 O(k)。因此,总的时间复杂度是 O(k log k + k) = O(k log k) = O((2k) log (2k)) = (O(n log n))。
由于每次递归都会将数组大小减半,所以每次递归的时间复杂度都是 (O(n log n))。因此,归并排序的时间复杂度是 (O(n log n))。
空间复杂度的证明类似,每次合并都需要一个大小为 n 的临时数组,所以总的空间复杂度是 (O(n))。
综上所述,归并排序的时间复杂度是 (O(n log n)),空间复杂度是 (O(n))。
多个函数版:
def merge(left, right): # Create an empty array to store the merged elements merged = [] # Initialize indexes for the left and right subarrays left_index = 0 right_index = 0 # Compare elements of the left and right subarrays and add them to the merged array while left_index < len(left) and right_index < len(right): if left[left_index] <= right[right_index]: merged.append(left[left_index]) left_index += 1 else: merged.append(right[right_index]) right_index += 1 # Add the remaining elements of the left subarray to the merged array merged += left[left_index:] # Add the remaining elements of the right subarray to the merged array merged += right[right_index:] # Return the merged array return merged def merge_sort(lst): # Check if the length of the array is less than or equal to 1 if len(lst) <= 1: # Return the array if it is return lst # Calculate the midpoint of the array mid = len(lst) // 2 # Create two subarrays, one from the start to the midpoint and one from the midpoint to the end left = merge_sort(lst[:mid]) right = merge_sort(lst[mid:]) # Merge the two subarrays and return the sorted array return merge(left, right)
单个函数版:
def mergeSort(arr): # Check if the length of the array is greater than 1 if len(arr) > 1: # Calculate the midpoint of the array mid = len(arr) // 2 # Create two subarrays, one from the start to the midpoint and one from the midpoint to the end left = arr[:mid] right = arr[mid:] # Recursively call the mergeSort function on each subarray mergeSort(left) mergeSort(right) # Initialize indexes for the left and right subarrays i = j = k = 0 # Compare elements of the left and right subarrays and add them to the sorted array while i < len(left) and j < len(right): if left[i] < right[j]: arr[k] = left[i] i += 1 else: arr[k] = right[j] j += 1 k += 1 # Add the remaining elements of the left subarray to the sorted array while i < len(left): arr[k] = left[i] i += 1 k += 1 # Add the remaining elements of the right subarray to the sorted array while j < len(right): arr[k] = right[j] j += 1 k += 1
def mergeNew(arr, l, m, r): n1 = m - l + 1 n2 = r - m L = [0] * n1 R = [0] * n2 for i in range(0, n1): L[i] = arr[l + i] for j in range(0, n2): R[j] = arr[m + 1 + j] i, j, k = 0, 0, l while i < n1 and j < n2: if L[i] <= R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 while i < n1: arr[k] = L[i] i += 1 k += 1 while j < n2: arr[k] = R[j] j += 1 k += 1 def merge_sort_bottom_up(arr): n = len(arr) size = 1 while size <= n - 1: for left_start in range(0, n - 1, 2 * size): mid = min(left_start + size - 1, n - 1) right_end = min(left_start + 2 * size - 1, n - 1) mergeNew(arr, left_start, mid, right_end) size = size * 2
template <typename T> vector<T> merge(vector<T> &left, vector<T> &right) { vector<T> merged; while (!left.empty() && !right.empty()) { // Compare the first elements of the two sublists if (left[0] <= right[0]) { // If left sublist's element is smaller, add it to the merged sublist merged.push_back(left[0]); // Erase the element from the sublist left.erase(left.begin()); } else { // If right sublist's element is smaller, add it to the merged sublist merged.push_back(right[0]); // Erase the element from the sublist right.erase(right.begin()); } } // Add the remaining elements of the left sublist to the merged sublist merged.insert(merged.end(), left.begin(), left.end()); // Add the remaining elements of the right sublist to the merged sublist merged.insert(merged.end(), right.begin(), right.end()); return merged; } template <typename T> vector<T> mergeSort(const vector<T> &list) { // If the list has one or less elements, it is already sorted if (list.size() <= 1) { return list; } // Find the midpoint of the list int mid = list.size() / 2; // Create two sublists, one from the beginning to the midpoint, and one from the midpoint to the end vector<T> left = mergeSort(vector<T>(list.begin(), list.begin() + mid)); vector<T> right = mergeSort(vector<T>(list.begin() + mid, list.end())); // Merge the two sublists and return the sorted list return merge(left, right); }
template <typename T> void mergeSortNonRecursive(vector<T> &arr) { // 1. Find the size of the array int n = arr.size(); // 2. Iterate through the array for (int size = 1; size < n; size *= 2) { // 3. Iterate through the array for (int leftStart = 0; leftStart < n - size; leftStart += 2 * size) { // 4. Find the mid point int mid = min(leftStart + size, n); // 5. Find the right start point int rightStart = min(leftStart + 2 * size, n); // 6. Create a temporary array int i = leftStart; int j = mid; int k = leftStart; vector<T> temp(arr.begin(), arr.end()); // 7. Compare the elements and move them to the temporary array while (i < mid && j < rightStart) { if (arr[i] <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } // 8. Move the remaining elements to the temporary array while (i < mid) { temp[k++] = arr[i++]; } while (j < rightStart) { temp[k++] = arr[j++]; } // 9. Copy the elements from the temporary array to the original array copy(temp.begin(), temp.end(), arr.begin()); } } }
自底向上的归并排序(Bottom-Up Merge Sort)是一种非递归的归并排序算法。它与传统的递归归并排序不同,不是一开始就将数组分成单个元素的小数组,然后再两两合并,而是从最小的数组块开始,逐步合并成更大的有序块,直到整个数组排序完成。
自底向上的归并排序(A)
n = A的长度
size = 1 // 初始子数组大小
while size < n
p = 0 // 子数组的起始索引
while p + size < n
q = p + size - 1 // 第一个子数组的结束索引
r = min((p + 2 * size - 1), (n - 1)) // 第二个子数组的结束索引
合并(A, p, q, r)
p = r + 1 // 更新下一个子数组的起始索引
size = size * 2 // 子数组大小翻倍
def mergeNew(arr, l, m, r): n1 = m - l + 1 n2 = r - m L = [0] * n1 R = [0] * n2 for i in range(0, n1): L[i] = arr[l + i] for j in range(0, n2): R[j] = arr[m + 1 + j] i, j, k = 0, 0, l while i < n1 and j < n2: if L[i] <= R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 while i < n1: arr[k] = L[i] i += 1 k += 1 while j < n2: arr[k] = R[j] j += 1 k += 1 def merge_sort_bottom_up(arr): n = len(arr) size = 1 while size <= n - 1: for left_start in range(0, n - 1, 2 * size): mid = min(left_start + size - 1, n - 1) right_end = min(left_start + 2 * size - 1, n - 1) mergeNew(arr, left_start, mid, right_end) size = size * 2
#include <iostream> #include <vector> #include <algorithm> using namespace std; // 合并两个有序数组A[p...q]和A[q+1...r] template <typename T> void Merge(vector<T>& A, int p, int q, int r) { int n1 = q - p + 1; int n2 = r - q; vector<T> L(n1); vector<T> R(n2); for (int i = 0; i < n1; i++) { L[i] = A[p + i]; } for (int j = 0; j < n2; j++) { R[j] = A[q + 1 + j]; } int i = 0, j = 0; for (int k = p; k <= r; k++) { if (i < n1 && (j >= n2 || L[i] <= R[j])) { A[k] = L[i]; i++; } else { A[k] = R[j]; j++; } } } // 自底向上的归并排序 template <typename T> void MergeSortBottomUp(vector<T>& A) { int n = A.size(); for (int size = 1; size < n; size *= 2) { for (int leftStart = 0; leftStart < n - size; leftStart += 2 * size) { int mid = leftStart + size - 1; int rightEnd = min(leftStart + 2 * size - 1, n - 1); Merge(A, leftStart, mid, rightEnd); } } } int main() { vector<int> arr = {5, 2, 4, 7, 1, 3, 2, 6}; MergeSortBottomUp(arr); for (int i = 0; i < arr.size(); i++) { cout << arr[i] << " "; } cout << endl; return 0; }
这段代码定义了一个模板函数MergeSortBottomUp
,它接受一个vector
类型的参数arr
,并对其进行自底向上的归并排序。函数使用两层循环:外层循环控制子数组的大小,内层循环遍历数组并合并相邻的子数组。在合并过程中,使用了一个临时数组L
和R
来存储合并前的子数组,然后再将合并后的结果复制回原数组arr
。
在main
函数中,我们创建了一个整数类型的vector
,并调用MergeSortBottomUp
进行排序,最后输出排序后的数组。
多路归并排序(Multi-Way Merge Sort)是一种改进的归并排序算法,它能够同时合并多个有序的子数组,而不是传统的归并排序中每次只合并两个子数组。这种方法可以显著提高大规模数据集的排序效率。
多路归并排序的核心思想是将多个有序的子数组合并成一个有序的大数组。它通常用于处理数据量非常大,以至于无法全部放入内存的情况。与传统的归并排序相比,多路归并排序可以在每个阶段并行处理更多的数据,从而减少整体排序时间。
多路归并排序(A)
n = A的长度
k = 子数组的数量 // 通常设置为处理器的数量或数据块的数量
大小 = 数据集大小 / k
将A分割成k个子数组,每个大小为大小
while 子数组的数量 > 1
合并相邻的子数组对,直到只剩下一个子数组
子数组的数量 = 子数组数量 / 2
返回有序的A
template <typename T> void multiwayMergeSort(vector<T> &arr, int k) { int n = arr.size(); if (n <= 1) return; vector<vector<T>> segments(k); for (int i = 0; i < n; ++i) { segments[i % k].push_back(arr[i]); } for (auto &segment : segments) { multiwayMergeSort(segment, k); } priority_queue<pair<T, int>, vector<pair<T, int>>, greater<>> pq; vector<int> indices(k, 0); for (int i = 0; i < k; ++i) { if (!segments[i].empty()) { pq.push({segments[i][0], i}); indices[i]++; } } arr.clear(); while (!pq.empty()) { auto [val, idx] = pq.top(); pq.pop(); arr.push_back(val); if (indices[idx] < segments[idx].size()) { pq.push({segments[idx][indices[idx]], idx}); indices[idx]++; } } } template <typename T> void multiway_merge_sort_non_recursive(vector<T> &data) { int k = data.size(); int current_size = 1; // Start with smallest sub-list size // Repeatedly merge sub-lists of increasing size while (current_size < k) { for (int left = 0; left < k; left += current_size * 2) { // Calculate right and mid indices for the current merge int mid = min(left + current_size, k); int right = min(left + current_size * 2, k); // Merge sub-lists [left, mid) and [mid, right) auto left_it = data.begin() + left, mid_it = data.begin() + mid; auto right_it = (right < k) ? data.begin() + right : data.end(); // Create temporary vector for merged elements vector<T> merged; // Merge elements until one sub-list is exhausted while (left_it != data.begin() + mid && mid_it != data.begin() + right) { if (*left_it <= *mid_it) { merged.push_back(*left_it); ++left_it; } else { merged.push_back(*mid_it); ++mid_it; } } // Add remaining elements from the non-exhausted sub-list merged.insert(merged.end(), left_it, data.begin() + mid); if (right_it != mid_it) { merged.insert(merged.end(), right_it, data.end()); } // Update the original data with the merged elements copy(merged.begin(), merged.end(), data.begin() + left); } current_size *= 2; // Double the sub-list size for next merge } }
#include <iostream> #include <array> #include <algorithm> #include <vector> #include <string> #include <vector> #include <queue> using namespace std; class Person { public: Person() = default; Person(string name, int age, int score) { this->name = name; this->age = age; this->socre = score; } // Override the operator> for other function to use. bool operator>(const Person &other) const { // Compare the socre of two Person objects. return this->socre > other.socre; } // Override the operator< for other function to use. bool operator<(const Person &other) const { // Compare the socre of two Person objects. return this->socre < other.socre; } // Override the operator== for other function to use. bool operator==(const Person &other) const { // Compare the socre, age and name of two Person objects. return this->socre == other.socre && this->age == other.age && this->name == other.name; } // Override the operator!= for other function to use. bool operator!=(const Person &other) const { // Compare the socre, age and name of two Person objects. return this->socre != other.socre || this->age != other.age || this->name != other.name; } // Override the operator<= for other fnction to use. bool operator<=(const Person &other) const { // Compare the socre, age and name of two Person objects. return this->socre <= other.socre && this->age <= other.age && this->name <= other.name; } // Override the operator>= for other function to use. bool operator>=(const Person &other) const { // Compare the socre, age and name of two Person objects. return this->socre >= other.socre && this->age >= other.age && this->name >= other.name; } // Now there are some get parameters function for this calss: const string &getName() const { return this->name; } int getAge() const { return this->age; } int getScore() const { return this->socre; } private: string name; int age = 0; int socre = 0; }; template <typename T> vector<T> merge(vector<T> &left, vector<T> &right) { vector<T> merged; while (!left.empty() && !right.empty()) { // Compare the first elements of the two sublists if (left[0] <= right[0]) { // If left sublist's element is smaller, add it to the merged sublist merged.push_back(left[0]); // Erase the element from the sublist left.erase(left.begin()); } else { // If right sublist's element is smaller, add it to the merged sublist merged.push_back(right[0]); // Erase the element from the sublist right.erase(right.begin()); } } // Add the remaining elements of the left sublist to the merged sublist merged.insert(merged.end(), left.begin(), left.end()); // Add the remaining elements of the right sublist to the merged sublist merged.insert(merged.end(), right.begin(), right.end()); return merged; } template <typename T> vector<T> mergeSort(const vector<T> &list) { // If the list has one or less elements, it is already sorted if (list.size() <= 1) { return list; } // Find the midpoint of the list int mid = list.size() / 2; // Create two sublists, one from the beginning to the midpoint, and one from the midpoint to the end vector<T> left = mergeSort(vector<T>(list.begin(), list.begin() + mid)); vector<T> right = mergeSort(vector<T>(list.begin() + mid, list.end())); // Merge the two sublists and return the sorted list return merge(left, right); } void mergeSortTestCase() { vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; mergeSort<int>(data); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; mergeSort<double>(dData); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; mergeSort<char>(cData); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; mergeSort<Person>(pData); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } template <typename T> vector<T> mergeOther(const vector<T> &left, const vector<T> &right) { vector<T> result; unsigned left_it = 0, right_it = 0; while (left_it < left.size() && right_it < right.size()) { // compare the current elements of the left and right vectors if (left[left_it] < right[right_it]) { // if the element of the left vector is less than the element of the right vector, add it to the result vector result.push_back(left[left_it]); left_it++; } else { // if the element of the left vector is greater than or equal to the element of the right vector, add it to the result vector result.push_back(right[right_it]); right_it++; } } // add the remaining elements of the left vector to the result vector while (left_it < left.size()) { result.push_back(left[left_it]); left_it++; } // add the remaining elements of the right vector to the result vector while (right_it < right.size()) { result.push_back(right[right_it]); right_it++; } return result; } template <typename T> vector<T> mergeSortOther(vector<T> &arr) { // if the vector is empty or contains only one element, return the vector if (arr.size() <= 1) { return arr; } // create two vectors, one to store the elements of the original vector before the split and one to store the elements after the split vector<T> left, right, result; int middle = ((int)arr.size() + 1) / 2; // copy the elements of the original vector into the left vector for (int i = 0; i < middle; i++) { left.push_back(arr[i]); } // copy the elements of the original vector into the right vector for (int i = middle; i < arr.size(); i++) { right.push_back(arr[i]); } // call the mergeSortOther function on the left and right vectors left = mergeSortOther(left); right = mergeSortOther(right); // call the mergeOther function to merge the sorted left and right vectors result = mergeOther(left, right); // return the merged sorted vector return result; } void mergeSortOtherTestCase() { vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; mergeSortOther<int>(data); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; mergeSortOther<double>(dData); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; mergeSortOther<char>(cData); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; mergeSortOther<Person>(pData); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } template <typename T> void mergeSortNonRecursive(vector<T> &arr) { // 1. Find the size of the array int n = arr.size(); // 2. Iterate through the array for (int size = 1; size < n; size *= 2) { // 3. Iterate through the array for (int leftStart = 0; leftStart < n - size; leftStart += 2 * size) { // 4. Find the mid point int mid = min(leftStart + size, n); // 5. Find the right start point int rightStart = min(leftStart + 2 * size, n); // 6. Create a temporary array int i = leftStart; int j = mid; int k = leftStart; vector<T> temp(arr.begin(), arr.end()); // 7. Compare the elements and move them to the temporary array while (i < mid && j < rightStart) { if (arr[i] <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } // 8. Move the remaining elements to the temporary array while (i < mid) { temp[k++] = arr[i++]; } while (j < rightStart) { temp[k++] = arr[j++]; } // 9. Copy the elements from the temporary array to the original array copy(temp.begin(), temp.end(), arr.begin()); } } } void mergeSortNonRecursiveTestCase() { vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; mergeSortNonRecursive<int>(data); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; mergeSortNonRecursive<double>(dData); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; mergeSortNonRecursive<char>(cData); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; mergeSortNonRecursive<Person>(pData); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } template <typename T> void Merge(vector<T> &A, int p, int q, int r) { // n1 is the size of the left sub array int n1 = q - p + 1; // n2 is the size of the right sub array int n2 = r - q; // Create two sub arrays L and R of size n1 and n2 respectively vector<T> L(n1); vector<T> R(n2); // Copy the elements of A from p to q into L for (int i = 0; i < n1; i++) { L[i] = A[p + i]; } // Copy the elements of A from q+1 to r into R for (int j = 0; j < n2; j++) { R[j] = A[q + 1 + j]; } // Initialize indexes i and j to 0 int i = 0, j = 0; // Merge the elements of L and R into A for (int k = p; k <= r; k++) { // If the element at index i of L is less than or equal to the element at index j of R if (i < n1 && (j >= n2 || L[i] <= R[j])) { // Copy the element at index i of L into A A[k] = L[i]; // Increment i i++; } else { // Copy the element at index j of R into A A[k] = R[j]; // Increment j j++; } } } template <typename T> void MergeSortBottomUp(vector<T> &A) { // n is the size of the array A int n = A.size(); // Iterate through the array A in a bottom up manner for (int size = 1; size < n; size *= 2) { // Iterate through the array A in a pair of sub arrays for (int leftStart = 0; leftStart < n - size; leftStart += 2 * size) { // mid is the mid point of the left sub array int mid = leftStart + size - 1; // rightEnd is the rightmost element of the right sub array int rightEnd = min(leftStart + 2 * size - 1, n - 1); // Merge the elements of the left and right sub arrays into A Merge<T>(A, leftStart, mid, rightEnd); } } } void mergeSortBottomUpTestCase() { vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; MergeSortBottomUp<int>(data); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; MergeSortBottomUp<double>(dData); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; MergeSortBottomUp<char>(cData); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; MergeSortBottomUp<Person>(pData); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } // Helper function for merging sub-lists template <typename T> void merge_bottom_up_sublist(vector<T> &data, size_t left, size_t mid, size_t right) { // Create temporary vector for holding merged elements vector<T> temp(right - left); // Copy elements from left and right sub-lists to the temp vector size_t i = left, j = mid, k = 0; while (i < mid && j < right) { if (data[i] <= data[j]) { temp[k++] = data[i++]; } else { temp[k++] = data[j++]; } } // Copy remaining elements from left sub-list while (i < mid) { temp[k++] = data[i++]; } // Copy remaining elements from right sub-list while (j < right) { temp[k++] = data[j++]; } // Copy merged elements back to the original vector copy(temp.begin(), temp.end(), data.begin() + left); } template <typename T> void merge_sort_bottom_up_non_recursive(vector<T> &data) { size_t n = data.size(); // Iterate through sub-list sizes from 1 to n/2 for (size_t sub_size = 1; sub_size <= n / 2; sub_size *= 2) { // Iterate through the data starting from left index for (size_t left = 0; left < n - sub_size; left += 2 * sub_size) { // Calculate right and mid indices for the merge size_t mid = min(left + sub_size, n); size_t right = min(left + 2 * sub_size, n); // Perform the merge operation merge_bottom_up_sublist<T>(data, left, mid, right); } } } void merge_sort_bottom_up_non_recursive_test_case() { vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; merge_sort_bottom_up_non_recursive<int>(data); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; merge_sort_bottom_up_non_recursive<double>(dData); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; merge_sort_bottom_up_non_recursive<char>(cData); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; merge_sort_bottom_up_non_recursive<Person>(pData); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } template <typename T> void multiwayMergeSort(vector<T> &arr, int k) { int n = arr.size(); if (n <= 1) return; vector<vector<T>> segments(k); for (int i = 0; i < n; ++i) { segments[i % k].push_back(arr[i]); } for (auto &segment : segments) { multiwayMergeSort(segment, k); } priority_queue<pair<T, int>, vector<pair<T, int>>, greater<>> pq; vector<int> indices(k, 0); for (int i = 0; i < k; ++i) { if (!segments[i].empty()) { pq.push({segments[i][0], i}); indices[i]++; } } arr.clear(); while (!pq.empty()) { auto [val, idx] = pq.top(); pq.pop(); arr.push_back(val); if (indices[idx] < segments[idx].size()) { pq.push({segments[idx][indices[idx]], idx}); indices[idx]++; } } } void multiWayMergeSortTestCase() { int mutilWayConunt = 4; vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; multiwayMergeSort<int>(data, mutilWayConunt); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; multiwayMergeSort<double>(dData, mutilWayConunt); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; multiwayMergeSort<char>(cData, mutilWayConunt); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; multiwayMergeSort<Person>(pData, mutilWayConunt); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } template <typename T> void multiway_merge_sort_non_recursive(vector<T> &data) { int k = data.size(); int current_size = 1; // Start with smallest sub-list size // Repeatedly merge sub-lists of increasing size while (current_size < k) { for (int left = 0; left < k; left += current_size * 2) { // Calculate right and mid indices for the current merge int mid = min(left + current_size, k); int right = min(left + current_size * 2, k); // Merge sub-lists [left, mid) and [mid, right) auto left_it = data.begin() + left, mid_it = data.begin() + mid; auto right_it = (right < k) ? data.begin() + right : data.end(); // Create temporary vector for merged elements vector<T> merged; // Merge elements until one sub-list is exhausted while (left_it != data.begin() + mid && mid_it != data.begin() + right) { if (*left_it <= *mid_it) { merged.push_back(*left_it); ++left_it; } else { merged.push_back(*mid_it); ++mid_it; } } // Add remaining elements from the non-exhausted sub-list merged.insert(merged.end(), left_it, data.begin() + mid); if (right_it != mid_it) { merged.insert(merged.end(), right_it, data.end()); } // Update the original data with the merged elements copy(merged.begin(), merged.end(), data.begin() + left); } current_size *= 2; // Double the sub-list size for next merge } } void multiway_merge_sort_non_recursive_test_case() { vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1}; multiway_merge_sort_non_recursive<int>(data); for (int i : data) { cout << i << " "; } cout << endl; vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1}; multiway_merge_sort_non_recursive<double>(dData); for (double i : dData) { cout << i << " "; } cout << endl; vector<char> cData = {'a', 'c', 'b', 'd', 'e'}; multiway_merge_sort_non_recursive<char>(cData); for (char i : cData) { cout << i << " "; } cout << endl; vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)}; multiway_merge_sort_non_recursive<Person>(pData); for (Person i : pData) { cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl; } cout << endl; } int main() { mergeSortTestCase(); mergeSortNonRecursiveTestCase(); mergeSortOtherTestCase(); mergeSortBottomUpTestCase(); multiWayMergeSortTestCase(); multiway_merge_sort_non_recursive_test_case(); merge_sort_bottom_up_non_recursive_test_case(); return 0; }
追寻与内心共鸣的生活,未来会逐渐揭晓答案。
Pursue the life that resonates with your heart, and the future will gradually reveal the answer.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。