Рекурсивные вызовы в сортировке слиянием - PullRequest
1 голос
/ 12 июля 2020

Выполнение сортировки слиянием и печать левой части дает мне следующий вывод для данного ввода, я не могу понять, почему он печатает 2 в конце. Пожалуйста, помогите мне с тем, как выглядят эти рекурсивные вызовы

Вход: (размер массива, а в следующей строке - массив)

5 
8 5 4 2 1

и результат

8
5 8
4 5 8
2
1 2 4 5 8

вот мой полный код для справки, это очень стандартный алгоритм, поэтому просто проверьте функцию mergesort и посмотрите, что я пытаюсь напечатать.

#include <bits/stdc++.h>

using namespace std;

vector<int> merge(vector<int>&B, vector<int>&C) {
    int n = B.size() + C.size();
    vector<int> D(n);
    for (int t{}; t < n; t++)
        D[t] = 0;
    int i{}, j{}, k{};
    
    while (i < B.size() && j < C.size()) {
        if (B[i] < C[j]) {
            D[k] = B[i];
            i++;
            k++;
        } else {
            D[k] = C[j];
            j++;
            k++;
        }
    }
    if (i < B.size()) {
        while (i < B.size()) {
            D[k] = B[i];
            k++;
            i++;
        }
    } else {
        while (j < C.size()) {
            D[k] = C[j];
            k++;
            j++;
        }
    }
    return D;
}

vector<int> merge_sort(vector<int> &A, int left, int right) {
    vector <int> B, C, A_;
    if (left == right) {
        A_.push_back(A[left]);  
        return A_;
    }
    int m = (left + right) / 2; //possible error, convert this to int then
    B = merge_sort(A, left, m);

    for (int i{}; i < B.size(); i++)
        cout << B[i] << " ";
    cout << endl;

    C = merge_sort(A, m + 1, right);
    A_ = merge(B, C);
    return A_;
}

int main() {
    int n; 
    cin >> n;
    vector<int> vec(n);
    for (int i{}; i < n; i++)
        cin >> vec[i];
    vector<int> sorted_vec = merge_sort(vec, 0, vec.size() - 1);
    
    for (int i{}; i < n; i++)
        cout << sorted_vec[i] << " ";
    cout << endl;
    
    return 0;
}

1 Ответ

3 голосов
/ 12 июля 2020

Это потому, что вы вызываете cout только в левой части вектора (для каждого вызова рекурсии) при первом посещении глубины: вы всегда печатаете, что происходит слева, и только для левых узлов (и после того, как левая сторона была отсортировано). Этот рисунок должен помочь вам понять:

введите описание изображения здесь

  • 85421 представляет ваш первый вызов merge_sort. Здесь у вас есть вектор B (854) и вектор C (21)

    • , затем вы вызываете merge_sort на 854. Здесь у вас есть вектор B (85) и вектор C (4)
      • затем вы вызываете merge_sort на 85. Здесь у вас есть вектор B (8) и вектор C (5)
        • Вектор с одним элементом сортируется.
      • вы печатаете вектор B (8)
      • вызываете merge_sort на (5)
        • вектор с одним элементом сортируется.
      • вы объединяете (8) и (5), чтобы получить (58)
      • , вы возвращаете (58) как B вызывающему методу
    • вы печатаете вектор B (58)
    • вы вызываете merge_sort на (4)
      • (4) уже отсортировано
    • вы объединяете (58) и (4) в (458) и верните (458) как B вызывающему методу
  • вы печатаете вектор B (458)

  • вы вызываете сортировку слиянием (21) вектор B равен (2), а вектор C равен (1)

    • вызовите сортировку слиянием в (2), и вы вернетесь (2) как B в вызывающем методе
    • вы печатаете (2)
    • вы вызываете merge_sort в (1)
    • вы объединяете (2) и (1) как (12) и отправьте (12) обратно как C вызывающему методу
  • вы объедините (458) и (12) и (12458) получите результат.

  • вы печатаете (12458) в основном

Надеюсь, это было полезно :)

...