c++14 - Merge Sort implementation outputs wrong results
问题描述
I am trying to implement Merge Sort in C++ 14. I've written the full code and proof-read it multiple times for logical faults but can't find any. But the code outputs a wrong sorted array that sometimes even contains duplicate elements and/or elements that were never input to the array in the first place.
Here's my code:
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
void merge_sort(vector<int>&, int, int);
void print_vector(vector<int>&);
void merge(vector<int>&, int, int, int);
int main() {
int arr_len = 0;
cout << "Enter the length of the array to be sorted: " << endl;
cin >> arr_len;
vector<int> arr(arr_len);
cout << "Enter the elements of the array: " << endl;
for (int i = 0; i < arr_len; i++) {
int buff;
cin >> buff;
arr[i] = buff;
}
cout << "The elements entered in the unsorted vector are: " << endl;
print_vector(arr);
merge_sort(arr, 0, arr_len - 1);
cout << "After Merge sorting, the elements in the vector are: " << endl;
print_vector(arr);
return 0;
}
void print_vector(vector<int>& arr) {
for (auto itr = arr.begin(); itr != arr.end(); ++itr) {
cout << *itr << " ";
}
cout << endl;
}
void merge_sort(vector<int>& arr, int low, int high) {
if (low < high) {
int mid = low + (high - low) / 2; // used this instead of (low + high) / 2 to avoid overflow problems
merge_sort(arr, low, mid); // recursive call to merge_sort with high = mid's updated value
merge_sort(arr, mid + 1, high);
merge(arr, low, mid, high); // call to merge to sort and merge the fragmented arrays.
}
}
void merge(vector<int>& arr, int low, int mid, int high) {
int l_arr_len = mid - low + 1;
int r_arr_len = high - mid;
vector<int> l_arr(l_arr_len);
vector<int> r_arr(r_arr_len);
for (int i = 0; i < l_arr_len; i++) { // initialise elements of temp_arr1 (l_arr) to 0.
l_arr[i] = 0;
}
for (int i = 0; i < r_arr_len; i++) { // initialise elements of temp_arr2 (r_arr) to 0.
r_arr[i] = 0;
}
for (int i = 0; i < l_arr_len; i++) { // transfer elements from arr to l_arr, upto length of the fragmented l_arr.
l_arr[i] = arr[low + i];
}
for (int i = 0; i < r_arr_len; i++) { // transfer remaining elements from arr to r_arr, upto length of the fragmented r_arr.
r_arr[i] = arr[mid + 1 + i];
}
int i = 0, j = 0, k = 0;
while (i < l_arr_len && j < r_arr_len) { // compare and replace elements in the mother array arr
if (l_arr[i] <= r_arr[j]) { // smallest element goes first
arr[k++] = l_arr[i++];
} else {
arr[k++] = r_arr[j++];
}
}
while (i < l_arr_len) { // write remaining elements in the left_arr fragment to mother array arr
arr[k++] = l_arr[i++];
}
while (j < r_arr_len) { // write remaining elements in the left_arr fragment to mother array arr
arr[k++] = r_arr[j++];
}
}
For an input array of elements [2, 9, 4, 5, 7]
, the correct sorted result would have been: [2, 4, 5, 7, 9]
.
But my implementation outputs: [5, 5, 7, 7, 9]
. I don't understand where the duplicate elements came from and why they replaced the original elements. While I've tried to add comments to almost statement out there for ease of access of the SO community, some of those may be redundant.
Since I'm out of my wits, please help me correct my code. You can point out what's wrong & where if that's what's convenient.
Thanks in advance! :)
解决方案
主要问题是别人发现的,k
必须初始化为,low
而不是0
.
您应该查看更多问题:
数组索引值和大小的正确类型是
size_t
, notint
,它的范围可能要小得多。传递最后一个元素的索引而不是排除的上限会产生带有索引调整的繁琐代码。
无需初始化临时向量,您应该只复制内容,或者更好地从数组切片构造它们。
print_vector
应该const
参考一下。
这是修改后的版本:
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
void merge_sort(vector<int>&, size_t, size_t);
void merge(vector<int>&, size_t, size_t, size_t);
void print_vector(const vector<int>&);
int main() {
size_t arr_len = 0;
cout << "Enter the length of the array to be sorted: " << endl;
cin >> arr_len;
vector<int> arr(arr_len);
cout << "Enter the elements of the array: " << endl;
for (size_t i = 0; i < arr_len; i++) {
cin >> arr[i];
}
cout << "The elements entered in the unsorted vector are: " << endl;
print_vector(arr);
merge_sort(arr, 0, arr_len);
cout << "After Merge sorting, the elements in the vector are: " << endl;
print_vector(arr);
return 0;
}
void print_vector(const vector<int>& arr) {
for (auto itr = arr.begin(); itr != arr.end(); ++itr) {
cout << *itr << " ";
}
cout << endl;
}
void merge_sort(vector<int>& arr, size_t low, size_t high) {
if (high - low > 1) {
size_t mid = low + (high - low) / 2; // used this instead of (low + high) / 2 to avoid overflow problems
merge_sort(arr, low, mid); // recursive call to merge_sort with high = mid's updated value
merge_sort(arr, mid, high);
merge(arr, low, mid, high); // call to merge to sort and merge the fragmented arrays.
}
}
void merge(vector<int>& arr, size_t low, size_t mid, size_t high) {
size_t l_arr_len = mid - low;
size_t r_arr_len = high - mid;
vector<int> l_arr(l_arr_len);
vector<int> r_arr(r_arr_len);
for (size_t i = 0; i < l_arr_len; i++) { // transfer elements from arr to l_arr, upto length of the fragmented l_arr.
l_arr[i] = arr[low + i];
}
for (size_t i = 0; i < r_arr_len; i++) { // transfer remaining elements from arr to r_arr, upto length of the fragmented r_arr.
r_arr[i] = arr[mid + i];
}
size_t i = 0, j = 0, k = low;
while (i < l_arr_len && j < r_arr_len) { // compare and replace elements in the mother array arr
if (l_arr[i] <= r_arr[j]) { // smallest element goes first
arr[k++] = l_arr[i++];
} else {
arr[k++] = r_arr[j++];
}
}
while (i < l_arr_len) { // write remaining elements in the left_arr fragment to mother array arr
arr[k++] = l_arr[i++];
}
while (j < r_arr_len) { // write remaining elements in the left_arr fragment to mother array arr
arr[k++] = r_arr[j++];
}
}
推荐阅读
- c# - 我可以使用 Source Generators 获取引用的项目代码吗?
- c# - 从索引位置到末尾搜索数组中的对象
- html - Bootstrap Carousel 弹跳,无法使用 HTML 和 CSS 进行编辑 - 包括 O/P gif
- string - 如何使用字符串中的单词在批处理文件中拆分字符串
- javascript - 通过对相关键求和,对数组中的键求和
- python - 如何在 python 中模仿 C# out 关键字功能来传递多个值
- php - 在 Memberpres 支付月费后设置用户角色
- github - 在 Github README 中获取用户选择的颜色主题
- sql - 将行插入视图 SQL 时出现主键错误
- azure-devops - Azure 数据工厂 YAML 部署在具有空格的 overrideParameter 键上失败