// // Implementation of merge sort algorithm. // // Driver generates and sorts a random sequence of N integers. // N and seed are passed as command-line arguments, with optional // "--verbose" to request verbose output (intermediate results). // // const DATA_LIMIT specifies upper bound for random data. // #include #include #include #include #include const int DATA_LIMIT = 100; void fillWithRandom(int seed, std::vector &v); void printVector(std::vector v); void mergeSort(std::vector &v, int p, int r, bool verbose); void merge(std::vector&v, int p, int q, int r, bool verbose); /* main (driver) */ int main(int argc, char *argv[]) { if (argc < 3) { std::cerr << "usage: " << argv[0] << "seed N [--verbose]" << std::endl; return EXIT_FAILURE; } char *endptr; long seed = strtol(argv[1], &endptr, 10); if (*endptr != '\0') { std::cerr << "non-numeric seed" << std::endl; return EXIT_FAILURE; } long n = strtol(argv[2], &endptr, 10); if (*endptr != '\0') { std::cerr << "non-numeric N" << std::endl; return EXIT_FAILURE; } bool verbose = (argc > 3) && (strcmp(argv[3], "--verbose") == 0); /* generate input */ std::vectorv(n); fillWithRandom(seed, v); std::cout << "Data before sort:\n"; printVector(v); mergeSort(v, 0, v.size()-1, verbose); std::cout << "\nData after sort:\n"; printVector(v); return EXIT_SUCCESS; } /* fill vector with random data */ void fillWithRandom(int seed, std::vector &v) { srand(seed); for (auto& iter : v) { iter = rand() % DATA_LIMIT; } } /* print vector */ void printVector(std::vector v) { for (int val : v) { std::cout << val << " "; } std::cout << std::endl; } /* * mergesort: * sort elements vector of n ints, from index p through index r */ void mergeSort(std::vector &v, int p, int r, bool verbose) { if (p >= r) if (verbose) { std::cout << "base case for p = " << p << ", r = " << r << std::endl; return; } int q = (p+r)/2; // find midpoint of elements to sort -- // no need for explicit "floor" because C will round/truncate mergeSort(v, p, q, verbose); mergeSort(v, q+1, r, verbose); merge(v, p, q, r, verbose); } /* * subprogram for mergesort -- merge two sorted vectors * (allocates work arrays every time -- probably not optimal except * in terms of readability!) */ void merge(std::vector&v, int p, int q, int r, bool verbose) { int nL = q - p + 1; int nR = r - q; std::vectorvL(nL); std::vectorvR(nR); for (int i = 0; i < nL; ++i) { vL[i] = v[p+i]; } for (int j = 0; j < nR; ++j) { vR[j] = v[q+j+1]; } if (verbose) { std::cout << "merging for p = " << p << ", q = " << q << ", r = " << r << std::endl; std::cout << "inputs:" << std::endl; std::cout << " "; printVector(vL); std::cout << " "; printVector(vR); } int i = 0; // smallest remaining element in vL int j = 0; // smallest remaining element in R int k = p; // next in v to fill while ((i < nL) && (j < nR)) { if (vL[i] <= vR[j]) { v[k] = vL[i]; i += 1; } else { v[k] = vR[j]; j += 1; } k += 1; } while (i < nL) { v[k] = vL[i]; i += 1; k += 1; } while (j < nR) { v[k] = vR[j]; j += 1; k += 1; } if (verbose) { std::cout << "result of merge: "; for (int kk = p; kk <= r; ++kk) { std::cout << v[kk] << " "; } std::cout << std::endl; } }