归并排序的基本思想:
分治法:归并排序将待排序数组分成两个子数组,分别对这两个子数组进行排序,然后将排序好的子数组合并,得到排序后的数组。
递归:通过递归的方式,不断地将数组一分为二,直到每个子数组只有一个元素(此时视为有序)。
合并:将两个有序子数组合并成一个有序数组。
void merge(vector<int>& arr, vector<int>& tempArr, int left, int mid, int right) {
//标记左半部分第一个未排序的元素
int l_pos = left;
//标记右半部分第一个未排序的元素
int r_pos = mid + 1;
//临时数组元素的下标,也就是排序后数组的起始位置
int pos = left;
//合并
while (l_pos <= mid && r_pos <= right) {
if (arr[l_pos] < arr[r_pos])
tempArr[pos++] = arr[l_pos++];
else
tempArr[pos++] = arr[r_pos++];
}
//合并左半区剩余的元素
while (l_pos <= mid)
tempArr[pos++] = arr[l_pos++];
//合并右半区剩余的元素
while (r_pos <= right)
tempArr[pos++] = arr[r_pos++];
//把临时数组合并后的元素赋值回原来的数组
while (left <= right) {
arr[left] = tempArr[left];
++left;
}
}
void mergeSort(vector<int>& arr, vector<int>& tempArr, int left, int right) {
//如果只有一个元素就不需要划分
if (left < right) {
int mid = (left + right) / 2;
//递归划分左半区
mergeSort(arr, tempArr, left, mid);
//递归划分右半区
mergeSort(arr, tempArr, mid + 1, right);
//合并已经排好序的部分
merge(arr, tempArr, left, mid, right);
}
}
int main() {
vector<int> nums{ 30, 24, 5, 58, 18, 36, 12, 42, 39 };
cout << "排序前:";
for (int num : nums)
cout << num << " ";
cout << endl;
vector<int> tempArr(nums.size());
mergeSort(nums, tempArr, 0, nums.size() - 1);
cout << "归并排序后:";
for (int num : nums)
cout << num << " ";
cout << endl;
}