所以,我一直在尝试创建一个合并排序算法,但由于某些原因,结果不正确。我试着在每次更改时打印高、低和中间值,以及数组值,我注意到有些值的数量甚至不正确。例如,如果我输入一个3,最终结果将包括多个3。但真正让我困惑的是,当我输入4个或更少的值时,这种情况不会发生,我只在5个或更高的输入值中注意到了这一点。我不知道是计算机或编译器在改变其中的一些值,还是我的代码出了问题。
这是我的代码:
#include <iostream>
#include <array>
int num;
int * array = new int [num];
int * sub = new int [num];
void sort (int low, int mid, int high) {
std::cout << "Low, mid, high: " << low << ", " << mid << ", " << high << ".n";
int a,b,c,d;
a = low;
b = low;
c = mid;
while ((a < mid) && (c < high)) {
if (array[a] < array[c]) {
sub[b] = array[a];
a++;
} else {
sub[b] = array[c];
c++;
}
b++;
}
while (a == mid && c < high) {
sub[b] = array[c];
c++;
b++;
}
while (c == high && a < mid) {
sub[b] = array[a];
a++;
b++;
}
for (d = low; d < high; d++) {
array[d] = sub[d];
for (int i = 0; i < num; i++) {
std::cout << array[i];
if (i != num - 1) {
std::cout << ", ";
} else {
std::cout << ".n";
}
}
}
std::cout << "Done!n";
}
void split (int low, int high) {
if (low < high - 1) {
int mid = (low + high) / 2;
split(low, mid);
split(mid, high);
sort(low, mid, high);
}
}
int main()
{
std::cout << "This is a program that sorts integers.n";
std::cout << "How many numbers would you like to sort?n";
std::cin >> num;
std::cout << "Please type in the numbers.n";
for (int i = 0; i < num; i++) {
std::cin >> array[i];
}
split(0, num);
std::cout << "Your sorted numbers are: ";
for (int i = 0; i < num; i++) {
std::cout << array[i];
if (i != num - 1) {
std::cout << ", ";
} else {
std::cout << ".n";
}
}
delete[] array;
delete[] sub;
return 0;
}
我还在我的原始编译器和一个在线shell上尝试了我的代码,似乎它们在同一测试中产生了两个不同的结果:
原始编译器:
This is a program that sorts integers.
How many numbers would you like to sort?
9
Please type in the numbers.
5
9
2
0
6
4
3
1
8
Low, mid, high: 0, 1, 2.
5, 9, 2, 0, 5, 9, 3, 1, 8.
5, 9, 2, 0, 5, 9, 3, 1, 8.
Done!
Low, mid, high: 2, 3, 4.
5, 9, 0, 0, 5, 9, 0, 2, 8.
5, 9, 0, 2, 5, 9, 0, 2, 8.
Done!
Low, mid, high: 0, 2, 4.
0, 9, 0, 2, 0, 2, 5, 9, 8.
0, 2, 0, 2, 0, 2, 5, 9, 8.
0, 2, 5, 2, 0, 2, 5, 9, 8.
0, 2, 5, 9, 0, 2, 5, 9, 8.
Done!
Low, mid, high: 4, 5, 6.
0, 2, 5, 9, 0, 2, 5, 9, 0.
0, 2, 5, 9, 0, 2, 5, 9, 0.
Done!
Low, mid, high: 7, 8, 9.
0, 2, 5, 9, 0, 2, 5, 0, 0.
0, 2, 5, 9, 0, 2, 5, 0, 9.
Done!
Low, mid, high: 6, 7, 9.
0, 2, 5, 9, 0, 2, 0, 0, 9.
0, 2, 5, 9, 0, 2, 0, 5, 9.
0, 2, 5, 9, 0, 2, 0, 5, 9.
Done!
Low, mid, high: 4, 6, 9.
0, 2, 5, 9, 0, 2, 0, 5, 0.
0, 2, 5, 9, 0, 0, 0, 5, 0.
0, 2, 5, 9, 0, 0, 2, 5, 0.
0, 2, 5, 9, 0, 0, 2, 5, 0.
0, 2, 5, 9, 0, 0, 2, 5, 0.
Done!
Low, mid, high: 0, 4, 9.
0, 2, 5, 9, 0, 0, 0, 0, 0.
0, 0, 5, 9, 0, 0, 0, 0, 0.
0, 0, 0, 9, 0, 0, 0, 0, 0.
0, 0, 0, 0, 0, 0, 0, 0, 0.
0, 0, 0, 0, 0, 0, 0, 0, 0.
0, 0, 0, 0, 0, 0, 0, 0, 0.
0, 0, 0, 0, 0, 0, 2, 0, 0.
0, 0, 0, 0, 0, 0, 2, 5, 0.
0, 0, 0, 0, 0, 0, 2, 5, 9.
Done!
Your sorted numbers are: 0, 0, 0, 0, 0, 0, 2, 5, 9.
Program ended with exit code: 0
在线外壳:
This is a program that sorts integers.
How many numbers would you like to sort?
9
Please type in the numbers.
5
9
2
0
6
4
3
1
8
Low, mid, high: 0, 1, 2.
5, 9, 2, 0, 6, 4, 3, 1, 5.
5, 9, 2, 0, 6, 4, 3, 1, 5.
Done!
Low, mid, high: 2, 3, 4.
5, 9, 0, 0, 6, 4, 3, 1, 5.
5, 9, 0, 2, 6, 4, 3, 1, 5.
Done!
Low, mid, high: 0, 2, 4.
0, 9, 0, 2, 6, 4, 3, 1, 0.
0, 2, 0, 2, 6, 4, 3, 1, 0.
0, 2, 5, 2, 6, 4, 3, 1, 0.
0, 2, 5, 9, 6, 4, 3, 1, 0.
Done!
Low, mid, high: 4, 5, 6.
0, 2, 5, 9, 4, 4, 3, 1, 0.
0, 2, 5, 9, 4, 6, 3, 1, 0.
Done!
Low, mid, high: 7, 8, 9.
0, 2, 5, 9, 4, 6, 3, 0, 0.
0, 2, 5, 9, 4, 6, 3, 0, 1.
Done!
Low, mid, high: 6, 7, 9.
0, 2, 5, 9, 4, 6, 0, 0, 1.
0, 2, 5, 9, 4, 6, 0, 1, 1.
0, 2, 5, 9, 4, 6, 0, 1, 3.
Done!
Low, mid, high: 4, 6, 9.
0, 2, 5, 9, 0, 6, 0, 1, 3.
0, 2, 5, 9, 0, 1, 0, 1, 3.
0, 2, 5, 9, 0, 1, 3, 1, 3.
0, 2, 5, 9, 0, 1, 3, 4, 3.
0, 2, 5, 9, 0, 1, 3, 4, 6.
Done!
Low, mid, high: 0, 4, 9.
0, 2, 5, 9, 0, 1, 3, 4, 0.
0, 0, 5, 9, 0, 1, 3, 4, 0.
0, 0, 1, 9, 0, 1, 3, 4, 0.
0, 0, 1, 2, 0, 1, 3, 4, 0.
0, 0, 1, 2, 3, 1, 3, 4, 0.
0, 0, 1, 2, 3, 4, 3, 4, 0.
0, 0, 1, 2, 3, 4, 0, 4, 0.
0, 0, 1, 2, 3, 4, 0, 5, 0.
0, 0, 1, 2, 3, 4, 0, 5, 9.
Done!
Your sorted numbers are: 0, 0, 1, 2, 3, 4, 0, 5, 9.
正如你所看到的,我使用了完全相同的数字和代码,但得到了两个完全不同的结果,所以我不知道我的代码是错的还是其他原因。感谢您提前提供的帮助。
由于num
在代码开头声明时没有定义,因此由于它是全局变量,num
被自动分配给0
。然后用用户尚未定义的num
声明int * array = new int [num];
和int * sub = new int [num];
,创建了两个具有0
元素的数组。试图更改这些数组会导致未定义的行为,包括错误地使某些事例看起来正确,在这种情况下,还使用了"不要在意"术语来更改用户创建的数字列表。
为了解决这个问题,必须在用户定义num
之后才能定义int * array
和int * sub
。这也意味着函数split
和sort
必须包括指向数组的指针作为参数。
代码应该是这样的:
#include <iostream>
#include <array>
void sort (int *array, int *sub, int low, int mid, int high) {
int a = low;
int b = low;
int c = mid;
while ((a < mid) && (c < high)) {
if (array[a] < array[c]) {
sub[b] = array[a];
a++;
} else {
sub[b] = array[c];
c++;
}
b++;
}
while (a == mid && c < high) {
sub[b] = array[c];
c++;
b++;
}
while (c == high && a < mid) {
sub[b] = array[a];
a++;
b++;
}
for (int d = low; d < high; d++) {
array[d] = sub[d];
}
}
void split (int *array, int *sub, int low, int high) {
if (low < high - 1) {
int mid = (low + high) / 2;
split(array, sub, low, mid);
split(array, sub, mid, high);
sort(array, sub, low, mid, high);
}
}
int main()
{
std::cout << "This is a program that sorts integers.n";
std::cout << "How many numbers would you like to sort?n";
int num;
std::cin >> num;
int * array = new int [num];
int * sub = new int [num];
std::cout << "Please type in the numbers.n";
for (int i = 0; i < num; i++) {
std::cin >> array[i];
}
split(array, sub, 0, num);
std::cout << "Your sorted numbers are: ";
for (int i = 0; i < num; i++) {
std::cout << array[i];
if (i != num - 1) {
std::cout << ", ";
} else {
std::cout << ".n";
}
}
delete[] array;
delete[] sub;
return 0;
}
您可以考虑使用自下而上的合并排序
自下而上:
template <typename T>
T * BottomUpMergeSort(T a[], T b[], size_t n)
{
for(size_t s = 1; s < n; s += 2) // swap in place for 1st pass
if(a[s] < a[s-1])
std::swap(a[s], a[s-1]);
for(size_t s = 2; s < n; s <<= 1){ // s = run size
size_t ee = 0; // init end index
while(ee < n){ // merge pairs of runs
size_t ll = ee; // ll = start of left run
size_t rr = ll+s; // rr = start of right run
if(rr >= n){ // if only left run
rr = n;
BottomUpCopy(a, b, ll, rr); // copy left run
break; // end of pass
}
ee = rr+s; // ee = end of right run
if(ee > n)
ee = n;
BottomUpMerge(a, b, ll, rr, ee);
}
std::swap(a, b); // swap a and b
}
return a; // return sorted array
}
template <typename T>
void BottomUpCopy(T a[], T b[], size_t ll, size_t rr)
{
while(ll < rr){ // copy left run
b[ll] = a[ll];
ll++;
}
}
template <typename T>
void BottomUpMerge(T a[], T b[], size_t ll, size_t rr, size_t ee)
{
size_t o = ll; // b[] index
size_t l = ll; // a[] left index
size_t r = rr; // a[] right index
while(1){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}
自上而下,通过交替使用两个递归函数来避免合并后的数据复制:
template <typename T>
T * TopDownMergeSort(T a[], T b[], size_t n)
{
TopDownMergeSortAtoA(a, b, 0, n);
return a;
}
template <typename T>
void TopDownMergeSortAtoA(T a[], T b[], size_t ll, size_t ee)
{
if (ee - ll > 1) {
size_t rr = (ll + ee)>>1; // midpoint, start of right half
TopDownMergeSortAtoB(a, b, ll, rr);
TopDownMergeSortAtoB(a, b, rr, ee);
TopDownMerge(b, a, ll, rr, ee); // merge b to a
}
}
template <typename T>
void TopDownMergeSortAtoB(T a[], T b[], size_t ll, size_t ee)
{
if (ee - ll > 1) {
size_t rr = (ll + ee)>>1; //midpoint, start of right half
TopDownMergeSortAtoA(a, b, ll, rr);
TopDownMergeSortAtoA(a, b, rr, ee);
TopDownMerge(a, b, ll, rr, ee); // merge a to b
} else if ((ee - ll) == 1) {
b[ll] = a[ll];
}
}
template <typename T>
void TopDownMerge(T a[], T b[], size_t ll, size_t rr, size_t ee)
{
size_t o = ll; // b[] index
size_t l = ll; // a[] left index
size_t r = rr; // a[] right index
while(1){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}