Многопроходная сортировка слиянием - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть функция mergeLists, которая принимает d отсортированные подсписки в качестве входных данных и дает один отсортированный объединенный список в качестве выходных данных.Это выглядит следующим образом:

    mergeLists (int d) {
        // Logic to Merge d sorted sub lists
        // Write the single big sorted list to file
    }

Теперь проблема возникает, когда слишком много подсписков.Я не могу объединить их всех одновременно.

РЕДАКТИРОВАТЬ: Мой код

struct MinHeapNode 
{ 
    // The element to be stored 
    int element; 

    // index of the array from which the element is taken 
    int i; 
}; 

// Prototype of a utility function to swap two min heap nodes 
void swap(MinHeapNode* x, MinHeapNode* y); 

// A class for Min Heap 
class MinHeap 
{ 
    MinHeapNode* harr; // pointer to array of elements in heap 
    int heap_size;   // size of min heap 

public: 
    // Constructor: creates a min heap of given size 
    MinHeap(MinHeapNode a[], int size); 

    // to heapify a subtree with root at given index 
    void MinHeapify(int); 

    // to get index of left child of node at index i 
    int left(int i) { return (2 * i + 1); } 

    // to get index of right child of node at index i 
    int right(int i) { return (2 * i + 2); } 

    // to get the root 
    MinHeapNode getMin() { return harr[0]; } 

    // to replace root with new node x and heapify() 
    // new root 
    void replaceMin(MinHeapNode x) 
    { 
        harr[0] = x; 
        MinHeapify(0); 
    } 
}; 

// Constructor: Builds a heap from a given array a[] 
// of given size 
MinHeap::MinHeap(MinHeapNode a[], int size) 
{ 
    heap_size = size; 
    harr = a; // store address of array 
    int i = (heap_size - 1) / 2; 
    while (i >= 0) 
    { 
        MinHeapify(i); 
        i--; 
    } 
} 

// A recursive method to heapify a subtree with root 
// at given index. This method assumes that the 
// subtrees are already heapified 
void MinHeap::MinHeapify(int i) 
{ 
    int l = left(i); 
    int r = right(i); 
    int smallest = i; 
    if (l < heap_size && harr[l].element < harr[i].element) 
        smallest = l; 
    if (r < heap_size && harr[r].element < harr[smallest].element) 
        smallest = r; 
    if (smallest != i) 
    { 
        swap(&harr[i], &harr[smallest]); 
        MinHeapify(smallest); 
    } 
} 

// A utility function to swap two elements 
void swap(MinHeapNode* x, MinHeapNode* y) 
{ 
    MinHeapNode temp = *x; 
    *x = *y; 
    *y = temp; 
} 

// Merges two subarrays of arr[]. 
// First subarray is arr[l..m] 
// Second subarray is arr[m+1..r] 
void merge(int arr[], int l, int m, int r) 
{ 
    int i, j, k; 
    int n1 = m - l + 1; 
    int n2 = r - m; 

    /* create temp arrays */
    int L[n1], R[n2]; 

    /* Copy data to temp arrays L[] and R[] */
    for(i = 0; i < n1; i++) 
        L[i] = arr[l + i]; 
    for(j = 0; j < n2; j++) 
        R[j] = arr[m + 1 + j]; 

    /* Merge the temp arrays back into arr[l..r]*/
    i = 0; // Initial index of first subarray 
    j = 0; // Initial index of second subarray 
    k = l; // Initial index of merged subarray 
    while (i < n1 && j < n2) 
    { 
        if (L[i] <= R[j]) 
            arr[k++] = L[i++]; 
        else
            arr[k++] = R[j++]; 
    } 

    /* Copy the remaining elements of L[], if there 
    are any */
    while (i < n1) 
        arr[k++] = L[i++]; 

    /* Copy the remaining elements of R[], if there 
    are any */
    while(j < n2) 
        arr[k++] = R[j++]; 
} 

FILE* openFile(char* fileName, char* mode) 
{ 
    FILE* fp = fopen(fileName, mode); 
    if (fp == NULL) 
    { 
        perror("Error while opening the file.\n"); 
        exit(EXIT_FAILURE); 
    } 
    return fp; 
} 

// Merges k sorted files. Names of files are assumed 
// to be 1, 2, 3, ... d 
void mergeFiles(char *output_file, int d) 
{ 
    FILE* in[d]; 
    for (int i = 0; i < d; i++) 
    { 
        char fileName[2]; 

        // convert i to string 
        snprintf(fileName, sizeof(fileName), "%d", i); 

        // Open output files in read mode. 
        in[i] = openFile(fileName, "r");
        remove(fileName);
    } 

    // FINAL OUTPUT FILE 
    FILE *out = openFile(output_file, "w"); 

    // Create a min heap with k heap nodes. Every heap node 
    // has first element of scratch output file 
    MinHeapNode* harr = new MinHeapNode[d]; 
    int i; 
    for (i = 0; i < d; i++) 
    { 
        // break if no output file is empty and 
        // index i will be no. of input files 
        if (fscanf(in[i], "%d ", &harr[i].element) != 1) 
            break; 

        harr[i].i = i; // Index of scratch output file 
    } 
    MinHeap hp(harr, i); // Create the heap 

    int count = 0; 

    // Now one by one get the minimum element from min 
    // heap and replace it with next element. 
    // run till all filled input files reach EOF 
    while (count != i) 
    { 
        // Get the minimum element and store it in output file 
        MinHeapNode root = hp.getMin(); 
        fprintf(out, "%d ", root.element); 

        // Find the next element that will replace current 
        // root of heap. The next element belongs to same 
        // input file as the current min element. 
        if (fscanf(in[root.i], "%d ", &root.element) != 1 ) 
        { 
            root.element = INT_MAX; 
            count++; 
        } 

        // Replace root with next element of input file 
        hp.replaceMin(root); 
    } 

    // close input and output files 
    for (int i = 0; i < d; i++) {
        fclose(in[i]);
    }

    fclose(out); 
}

Можете ли вы предложить мне твик, с помощью которого я могу реализовать какую-то рекурсию или что-то, что позволяет мне делать следующее:

Повторно, пока не останется только один список, объедините подсписки d (учитывая n подсписков в начале и n >> d)

...