C++ - 合并排序 - 无法确定问题所在



所以,我一直在尝试创建一个合并排序算法,但由于某些原因,结果不正确。我试着在每次更改时打印高、低和中间值,以及数组值,我注意到有些值的数量甚至不正确。例如,如果我输入一个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 * arrayint * sub。这也意味着函数splitsort必须包括指向数组的指针作为参数。

代码应该是这样的:

#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
        }
    }
}

最新更新