合并排序不正确的输出 c++
Mergesort incorrect output c++
输入:{10,9,8,7,6,5,4,3,2,1}
输出 :{8,7,6,9,10,5,4,3,2,1}
我不确定问题是什么。我认为这与合并排序中的递归有关。我是递归的新手,所以我的理解不是很好。有什么提示吗?
#include <iostream>
void mergeSort(int a[], int w[], int n);
void merge(int a[], int w[], int n);
using namespace std;
void mergeSort(int a[], int t[], int n) {
if (n > 1) {
for (int i = 0; i < n/2; i++) {
t[i] = a[i];
}
mergeSort(a, t, n/2);
for (int i = n/2; i < n; i++) {
t[i] = a[i];
}
mergeSort(a, t, n/2);
merge(a, t, n/2);
}
}
void merge(int a[], int t[], int n) {
int leftIndex = 0, leftEnd = n/2;
int rightIndex = n/2, rightEnd = n;
int targetIndex = 0;
while (leftIndex < leftEnd && rightIndex < rightEnd) {
if (t[leftIndex] < t[rightIndex])
a[targetIndex++] = t[leftIndex++];
else
a[targetIndex++] = t[rightIndex++];
}
while (leftIndex < leftEnd) {
a[targetIndex++] = t[leftIndex++];
}
while (rightIndex < rightEnd) {
a[targetIndex++] = t[rightIndex++];
}
}
int main() {
const int SIZE = 10;
int a[] = {10,9,8,7,6,5,4,3,2,1};
int w[SIZE];
mergeSort(a,w,SIZE);
for (int i = 0; i < SIZE; i++) {
cout << a[i] << " ";
}
cout << endl;
}
一般问题是指针混淆。C 语言的一个怪癖并不明显,那就是在
void mergeSort(int a[], int t[], int n);
a
和t
都不是数组,而是指针。在语言标准中对此有一条特殊规则。这意味着在调用堆栈上mergeSort
的所有实例化中,t
和a
引用相同的内存区域,这意味着每次您执行类似
for (int i = 0; i < n/2; i++) {
t[i] = a[i];
}
您正在更改相同的内存区域。执行此操作并返回到上一个调用帧后,此区域将不再包含您希望它包含的数据。
解决此问题的方法是在您需要的地方定义一个临时本地缓冲区,该缓冲区位于merge
中。例如:
const int SIZE = 10;
// mergeSort is much simpler now:
void mergeSort(int a[], int n) {
if (n > 1) {
// sort the left side, then the right side
mergeSort(a , n / 2);
mergeSort(a + n / 2, n - n / 2);
// then merge them.
merge(a, n);
}
}
// Buffer work done in merge:
void merge(int a[], int n) {
// temporary buffer t, big enough to hold the left side
int t[SIZE];
int leftIndex = 0 , leftEnd = n / 2;
int rightIndex = n / 2, rightEnd = n ;
int targetIndex = 0;
// copy the left side of the target array into the temporary
// buffer so we can overwrite that left side without worrying
// about overwriting data we haven't yet merged
for(int i = leftIndex; i < leftEnd; ++i) {
t[i] = a[i];
}
// then merge the right side and the temporary buffer to
// the left side. By the time we start overwriting stuff on
// the right side, the values we're overwriting will have been
// merged somewhere into the left side, so this is okay.
while (leftIndex < leftEnd && rightIndex < rightEnd) {
if (t[leftIndex] < a[rightIndex]) {
a[targetIndex++] = t[leftIndex++];
} else {
a[targetIndex++] = a[rightIndex++];
}
}
// If there's stuff in the temporary buffer left over,
// copy it to the end of the target array. If stuff on the
// right is left over, it's already in the right place.
while (leftIndex < leftEnd) {
a[targetIndex++] = t[leftIndex++];
}
}
在解释错误之前,让我首先强调一下,像int a[]
这样的函数参数只不过是传递给函数的指针。它指向内存区域。
现在,mergesort
需要一些临时内存,并且通过以下方式工作
- 将数据复制到临时存储器;
- 对临时内存中的每一半数据进行排序;
- 合并两半,从而写入原始数组。
在步骤 2 中,不需要原始数组,可以用作递归的临时内存。
鉴于这些事实,您的代码包含两个错误:
-
您没有正确使用数组
t[]
和a[]
。这个想法是a[]
既是输入又是输出,t[]
临时数组。在内部,数据首先被复制到临时数组中,其中的每一部分都经过排序,然后合并它们填充原始数组a[]
。 -
您不会对临时数组的后半部分进行排序,而是对前半部分进行两次排序。
例如,正确的实现是:
void mergeSort(int*a, int*t, int n) {
if (n > 1) {
for (int i = 0; i < n; i++)
t[i] = a[i]; // copy to temporary
mergeSort(t , a , n/2); // sort 1st half of temporary
mergeSort(t+n/2, a+n/2, n-n/2); // sort 2nd half of temporary
merge(a, t, n);
}
}
请注意,由于t[]
和a[]
是指针,因此操作t+n/2
只是获取指向数组后半部分的指针。具有此更改的代码的结果是1 2 3 4 5 6 7 8 9 10
。
相关文章:
- 递归函数计算序列中的平方和(并输出过程)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 请解释"函数1(p1,p2,p3);"的输出
- C++:将控制台输出存储在宏中更好吗
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 为什么我的代码在输出中增加了93天
- 如何从void函数输出字符串
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- AES加密到解密未正确输出
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++格式化输出问题
- 将值从二维数组输出到文本文件
- 集合上的输出迭代器:assign和increment迭代器
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 为什么rk4.do_step不输出C++中的初始条件
- 输出没有重复元素的动态数组(收缩数组)C++
- 如何根据单词在文本中出现的概率输出单词