Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed last year.
I am trying to generate every combination of four numbers from (-1,-0.99,-0.98,...0.98,0.99,1) that sum up to 1.
I have tried to it in C++ but it is not working as I want.
Here is the example:
// C++ program for to print all combination
// of 4 elements in A[] with sum equal to X
#include<bits/stdc++.h>
using namespace std;
/* Following function is needed
for library function qsort(). */
int compare (const void *a, const void * b)
{
return ( *(int *)a - *(int *)b );
}
/* A sorting based solution to print
all combination of 4 elements in A[]
with sum equal to X */
void find4Numbers(double A[], int n, double X)
{
int l, r;
// Sort the array in increasing
// order, using library function
// for quick sort
qsort (A, n, sizeof(A[0]), compare);
/* Now fix the first 2 elements
one by one and find
the other two elements */
for (int i = 0; i < n - 3; i++)
{
for (int j = i+1; j < n - 2; j++)
{
// Initialize two variables as
// indexes of the first and last
// elements in the remaining elements
l = j + 1;
r = n-1;
// To find the remaining two
// elements, move the index
// variables (l & r) toward each other.
while (l < r)
{
if( A[i] + A[j] + A[l] + A[r] == X)
{
cout << A[i]<<", " << A[j] <<
", " << A[l] << ", " << A[r] << endl;
l++; r--;
}
else if (A[i] + A[j] + A[l] + A[r] < X)
l++;
else // A[i] + A[j] + A[l] + A[r] > X
r--;
} // end of while
} // end of inner for loop
} // end of outer for loop
}
/* Driver code */
int main()
{
/*int A[202];
for(int i=0; i<201; i++){
A[i]={i};
}
A[202]=0;
int X = 70;
int n = 202;*/
double A[] = {-1,-0.99,-0.98,-0.97,-0.96,-0.95,-0.94,-0.93,-0.92,-0.91,-0.9,-0.89,-0.88,-0.87,-0.86,-0.85,-0.84,-0.83,-0.82,-0.81,-0.8,-0.79,-0.78,-0.77,-0.76,-0.75,-0.74,-0.73,-0.72,-0.71,-0.7,-0.69,-0.68,-0.67,-0.66,-0.65,-0.64,-0.63,-0.62,-0.61,-0.6,-0.59,-0.58,-0.57,-0.56,-0.55,-0.54,-0.53,-0.52,-0.51,-0.5,-0.49,-0.48,-0.47,-0.46,-0.45,-0.44,-0.43,-0.42,-0.41,-0.4,-0.39,-0.38,-0.37,-0.36,-0.35,-0.34,-0.33,-0.32,-0.31,-0.3,-0.29,-0.28,-0.27,-0.26,-0.25,-0.24,-0.23,-0.22,-0.21,-0.2,-0.19,-0.18,-0.17,-0.16,-0.15,-0.14,-0.13,-0.12,-0.11,-0.1,-0.09,-0.08,-0.07,-0.06,-0.05,-0.04,-0.03,-0.02,0.01,0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1
};
double X = 1;
int n = sizeof(A) / sizeof(A[0]);
find4Numbers(A, n, X);
return 0;
}
It gives numbers that sum to 1 but the output does not give every combination. For example numbers 0,1,0.12,-0.12 does not show up. I am looking for the list of these numbers, I don't even need a code. Numbers can duplicate so (0,0,0.5, 0.5) is okay, too.
Can you have any tips where could I generate the list or how to make a program that gives one?
For starters, your compare function is wrong since you are comparing int instead of double. Therefore try:
int compare (const void *a, const void * b)
{
double ca = *((double *) a);
double cb = *((double *) b);
return (ca > cb) - (ca < cb);
}
I have implemented an algorithm that solves the problem of finding the kth smallest element in an unsorted array. I have used the heap structure, and optimized the code by relying on this formula,
k1 = n - k + 1
k1 being the k1th largest element, so I go for the smaller of k and k1.
Still, I couldn't pass the time limit error on an online judge. I don't know if there will be any further more better complexity having in mind that I have to create an array no more than the size of k; maybe less than k possible? Or there is another way to solve this problem other than using the heap structure.
1 <= k <= n <= 105
The code:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
void minHeapify(int arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
if (l < n && arr[l] < arr[largest])
largest = l;
if (r < n && arr[r] < arr[largest])
largest = r;
if (largest != i) {
swap(arr[i], arr[largest]);
minHeapify(arr, n, largest);
}
}
void maxHeapify(int arr[], int n, int i)
{
int smallest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
if (l < n && arr[l] > arr[smallest])
smallest = l;
if (r < n && arr[r] > arr[smallest])
smallest = r;
if (smallest != i) {
swap(arr[i], arr[smallest]);
maxHeapify(arr, n, smallest);
}
}
void buildMinHeap(int a[], int n) {
for (int i = n / 2; i >= 0; i--)
minHeapify(a, n, i);
}
void buildMaxHeap(int a[], int n) {
for (int i = n / 2; i >= 0; i--)
maxHeapify(a, n, i);
}
int kthsmallest(int minHeap[], int k, int n) {
int i, temp;
for (i = 0; i < k; i++)
cin >> minHeap[i];
buildMaxHeap(minHeap, k);
for (i = k; i < n; i++)
{
cin >> temp;
if (temp < minHeap[0])
{
minHeap[0] = temp;
maxHeapify(minHeap, k, 0);
}
}
return minHeap[0];
}
int kthlargest(int minHeap[], int k, int n) {
int i, temp;
for (i = 0; i < k; i++)
cin >> minHeap[i];
buildMinHeap(minHeap, k);
for (i = k; i < n; i++)
{
cin >> temp;
if (temp > minHeap[0])
{
minHeap[0] = temp;
minHeapify(minHeap, k, 0);
}
}
return minHeap[0];
}
int main() {//kth smallest element
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n, k, k1;
cin >> n >> k;
k1 = n - k + 1;//kth smallest element is the same as k1th largest element
if (k < k1) {
int *minHeap = new int[k];
cout << kthsmallest(minHeap, k, n);
}
else {
int *minHeap = new int[k1];
cout << kthlargest(minHeap, k1, n);
}
return 0;
}
Please if you could help finding a better time complexity?
Problem:
Find the kth largest element of an array
Memory limit: 256 MBs
Time limit: 1 s
Input: input.txt
Output: output.txt
Task:
You are given an array of n integers and a natural k.
You have to find the kth largest element of the array.
You can't create array consisting of more than k elements.
Input:
The first line contains a natural n (1 ≤ n≤105) – the
quantity of elements of the array, and the natural k.
The second line contains n numbers – the elements of the array.
Output:
The kth largest element of the array.
Example:
Input | Output
-------------+-----------
6 2 | 7
7 4 6 3 9 1 |
The time complexity is optimal, but you can make your code a tiny bit more efficient:
Don't use recursion, but an iterative solution
Don't use swap, but keep the original value in memory while copying child values to their parents and only store the initial value once you have reached the appropriate slot.
Don't perform twice 2 * i: the other child node is just the next one.
Let the heapify functions take an extra argument, which can be either the current value at index i, or the replacement value for it. This saves one assignment.
Here is how that would look for two heapify functions:
void minHeapify(int arr[], int n, int i, int key) { // add key as parameter
while (true) { // iterative
int child = 2 * i + 1; // do this only for left child, and limit number of variables
if (child+1 < n && arr[child] > arr[child+1]) // get child with least value
child++; // the right child is just one index further
if (child >= n || key <= arr[child]) break;
arr[i] = arr[child]; // don't swap, just copy child value to parent
i = child; // move down
}
arr[i] = key; // finally put the original value in the correct place
}
void maxHeapify(int arr[], int n, int i, int key) { // add key as parameter
while (true) { // iterative
int child = 2 * i + 1; // do this only for left child, and limit number of variables
if (child+1 < n && arr[child] < arr[child+1]) // get child with greatest value
child++; // the right child is just one index further
if (child >= n || key >= arr[child]) break;
arr[i] = arr[child]; // don't swap, just copy child value to parent
i = child; // move down
}
arr[i] = key; // finally put the original value in the correct place
}
void buildMinHeap(int a[], int n) {
for (int i = n / 2; i >= 0; i--)
minHeapify(a, n, i, a[i]); // pass a[i] also
}
void buildMaxHeap(int a[], int n) {
for (int i = n / 2; i >= 0; i--)
maxHeapify(a, n, i, a[i]); // pass a[i] also
}
int kthsmallest(int heap[], int k, int n) {
int i, temp;
for (i = 0; i < k; i++)
cin >> heap[i];
buildMaxHeap(heap, k);
for (i = k; i < n; i++) {
cin >> temp;
if (temp < heap[0])
maxHeapify(heap, k, 0, temp); // pass temp
}
return heap[0];
}
int kthlargest(int heap[], int k, int n) {
int i, temp;
for (i = 0; i < k; i++)
cin >> heap[i];
buildMinHeap(heap, k);
for (i = k; i < n; i++) {
cin >> temp;
if (temp > heap[0])
minHeapify(heap, k, 0, temp); // pass temp
}
return heap[0];
}
In main function you could make a special case for when k == 1 or k == n, so no heap is needed, just min() or max().
One strange thing is that the challenge you link to speaks of "kth largest" while you speak of "kth smallest". Maybe you mixed up.
So here is the code when the job is to return the kth smallest. But please check the challenge whether you should not have done it for kth largest:
int main() {//kth smallest element
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n, k, k1;
cin >> n >> k;
k1 = n - k + 1;//kth smallest element is the same as k1th largest element
if (k == 1) {
int curr, next;
cin >> curr;
for (int i = 1; i < n; i++) {
cin >> next;
curr = min(curr, next);
}
cout << curr;
} else if (k1 == 1) {
int curr, next;
cin >> curr;
for (int i = 1; i < n; i++) {
cin >> next;
curr = max(curr, next);
}
cout << curr;
} else if (k < k1) {
int *heap = new int[k];
cout << kthsmallest(heap, k, n);
} else {
int *heap = new int[k1];
cout << kthlargest(heap, k1, n);
}
return 0;
}
You're making the assumption that using a smaller heap is always the best choice. You might want to re-think that.
For example, imagine you want to select the 96th smallest number from a list of 100. If you use a heap of size 96, then you'll do:
Build a heap with 96 items. buildHeap is O(n), and in this case n is 96.
Do up to 4 insertions into a heap of 96 items. That'll be 4*log(96).
If you use a heap of size 4, then you'll do:
Build a heap with 4 items.
Do up to 96 insertions into a heap of 4 items. That'll be 96*log(4).
The first option is 96 + 4*log(96). The base-2 log of 96 is about 6.58. So the insertions will cost 26.32, for a total of 122.32.
The second option, with the smaller heap, is 4 + 96*log(4). log(4) is 2, so you end up with 4 + 196, or a total of 196.
The smaller heap is a big loser here.
In general, you want to use the larger heap when (k + (n-k)*log(k)) < ((n-k) + k*log(n-k)).
Also:
The real-world running time of the heap selection algorithm is kind of sensitive to the order in which items are presented. For example, if you're looking for 1000th smallest number in an array of 100,000, it's going to run much faster if the array is in ascending order than if it's in descending order. The reason?
Because in the ascending case, you build your initial heap with the first 1,000 items and then you never have to modify the heap again because there is none of the following items are smaller than the largest item on the heap.
But if the array is in descending order, then every item you look at will be smaller than the largest item on the heap, which means you'd be doing a heap insertion for all 99,000 remaining items.
Imagine how your code would perform if one of the test cases is a large array in descending order.
Unless you've already proven that your way of selecting which heap size to use is clearly better, you might want to consider just going with "select kth smallest," using a maxheap of size k, regardless.
//
// main.cpp
// timsort
//
// Created by Atharva Koli on 2019/1/27.
// Copyright © 2019 Atharva Koli. All rights reserved.
//
#include<bits/stdc++.h>
using namespace std;
const int RUN = 32;
// this function sorts array from left index to
// to right index which is of size atmost RUN
void insertionSort(int arr[], int left, int right)
{
for (int i = left + 1; i <= right; i++)
{
int temp = arr[i];
int j = i - 1;
while (arr[j] > temp && j >= left)
{
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp;
}
}
// merge function merges the sorted runs
void merge(int arr[], int l, int m, int r)
{
// original array is broken in two parts
// left and right array
int len1 = m - l + 1, len2 = r - m;
int left[len1], right[len2];
for (int i = 0; i < len1; i++)
left[i] = arr[l + i];
for (int i = 0; i < len2; i++)
right[i] = arr[m + 1 + i];
int i = 0;
int j = 0;
int k = l;
// after comparing, we merge those two array
// in larger sub array
while (i < len1 && j < len2)
{
if (left[i] <= right[j])
{
arr[k] = left[i];
i++;
}
else
{
arr[k] = right[j];
j++;
}
k++;
}
// copy remaining elements of left, if any
while (i < len1)
{
arr[k] = left[i];
k++;
i++;
}
// copy remaining element of right, if any
while (j < len2)
{
arr[k] = right[j];
k++;
j++;
}
}
// iterative Timsort function to sort the
// array[0...n-1] (similar to merge sort)
void timSort(int arr[], int n)
{
// Sort individual subarrays of size RUN
for (int i = 0; i < n; i+=RUN)
insertionSort(arr, i, min((i+31), (n-1)));
// start merging from size RUN (or 32). It will merge
// to form size 64, then 128, 256 and so on ....
for (int size = RUN; size < n; size = 2*size)
{
// pick starting point of left sub array. We
// are going to merge arr[left..left+size-1]
// and arr[left+size, left+2*size-1]
// After every merge, we increase left by 2*size
for (int left = 0; left < n; left += 2*size)
{
// find ending point of left sub array
// mid+1 is starting point of right sub array
int mid = left + size - 1;
int right = min((left + 2*size - 1), (n-1));
// merge sub array arr[left.....mid] &
// arr[mid+1....right]
merge(arr, left, mid, right);
}
}
}
// utility function to print the Array
void printArray(int arr[], int n)
{
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
// Driver program to test above function
int main()
{
int arr[] = {"10 thousand numbers separated by commas"};
int n = sizeof(arr)/sizeof(arr[0]);
timSort(arr, n);
printArray(arr, n);
return 0;
}
This is a program I wrote which sorts the numbers contained in an array using the timsort algorithm. The program compiled and ran successfully using 100, 1000...numbers. However when I put 10,000 numbers or more in the array the program crashes giving me a compile error like so:
Xcode Compile Error
I am still a beginner in C++ programming and the code above is combined using various sources online. Please assist me in identifying the issue!
The program is a standard implementation of timsort, efficiently combining arrays sorted using insertion sort.
You have out of bound problem, though it doesn't reveal itself instantly. Firstly you use non-standard extension called VLA inside of merge(), so how those arrays behaves in stack, I'm not sure. Secondly, the index math in merge results in
l,len1 =0,32
l,len1 =64,32
l,len1 =128,32
l,len1 =192,32
...
l,len1 =9472,32
l,len1 =9536,32
l,len1 =9600,32
l,len1 =9664,32
l,len1 =9728,32
l,len1 =9792,32
l,len1 =9856,32
l,len1 =9920,32
l,len1 =9984,32
9984 + 32 > 10000 , so accessing arr[l + i] results in reading past the end of array. After few iteration it reaches state where that would cause segmentation fault. Try print your variables to debug it.
I was trying to solve the quick sort - 2 challenge on hackerrank. It said that we had to repeatedly call partition till the entire array was sorted. My program works for some test cases but for some it crashes, "Quick Sort - 2.exe has stopped working". I couldn't find the reason as to why it's happening.
The first element of the array/sub-array was to be taken as pivot element each time.
#include <iostream>
#include <conio.h>
using namespace std;
void swap(int arr[], int a, int b)
{
int c = arr[a];
arr[a] = arr[b];
arr[b] = c;
}
void qsort(int arr[], int m, int n) //m - lower limit, n - upper limit
{
if (n - m == 1)
{
return;
}
int p = arr[m], i, j, t; //p - pivot element, t - temporary
//partition
for (int i = m+1; i < n; i++)
{
j = i;
if (arr[j] < p)
{
t = arr[j];
while (arr[j] != p)
{
arr[j] = arr[j-1];
j--;
}
arr[j] = t; //pivot is at j and j+1
}
}
//check if sorted
int f = 1;
while (arr[f] > arr[f-1])
{
if (f == n-1)
{
f = -1;
break;
}
f++;
}
if (f == -1)
{
cout << "Sub Array Sorted\n";
}
else
{
if (p == arr[m]) //pivot is the smallest in sub array
{
qsort(arr, m+1, n); //sort right sub array
}
else
{
qsort(arr, m, j+1); //sort left sub array
qsort(arr, j+1, n); //sort right sub array
}
}
}
int main()
{
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
qsort(arr, 0, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
return 0;
}
You have an index out of range problem.
This will not give you the solution, but it may help you to find the reason why your program fails.
I have modified your program so it uses a vector of int rather than a raw array of int, and when you run this program you get an index out of range exception.
The sequence 4 3 7 1 6 4 that triggers the problem is hardcoded, so you don't need to type it each time.
#include <iostream>
#include <vector>
using namespace std;
void swap(vector<int> & arr, int a, int b)
{
int c = arr[a];
arr[a] = arr[b];
arr[b] = c;
}
void qsort(vector<int> & arr, int m, int n) //m - lower limit, n - upper limit
{
if (n - m == 1)
{
return;
}
int p = arr[m], j, t; //p - pivot element, t - temporary
//partition
for (int i = m + 1; i < n; i++)
{
j = i;
if (arr[j] < p)
{
t = arr[j];
while (arr[j] != p)
{
arr[j] = arr[j - 1];
j--;
}
arr[j] = t; //pivot is at j and j+1
}
}
//check if sorted
int f = 1;
while (arr[f] > arr[f - 1])
{
if (f == n - 1)
{
f = -1;
break;
}
f++;
}
if (f == -1)
{
cout << "Sub Array Sorted\n";
}
else
{
if (p == arr[m]) //pivot is the smallest in sub array
{
qsort(arr, m + 1, n); //sort right sub array
}
else
{
qsort(arr, m, j + 1); //sort left sub array
qsort(arr, j + 1, n); //sort right sub array
}
}
}
int main()
{
vector<int> arr = { 4,3,7,1,6,4 };
qsort(arr, 0, arr.size());
for (unsigned int i = 0; i < arr.size(); i++)
{
cout << arr[i] << " ";
}
return 0;
}
First of all, what you made is not quick sort, but some combination of divide-ans-conquer partitioning and insert sort.
Canonical quicksort goes from from lower (p) and upper (q) bounds of array, skipping elements arr[p]m respectively. Then it swaps arr[p] with arr[q], increments/decrements and checks if p>=q. Rinse and repeat until p>=q. Then make calls on sub-partitions. This way p or q holds pivot position and subcalls are obvious.
But you are doing it different way: you insert elements from right side of subarray to left side. Such thing can produce O(N^2) time complexity for one iteration. Consider 1,0,1,0,1,0,1,0,1,0,1,0,... sequence, for example. This can increase worst case complexity over O(N^2).
Out of time complexity... The problem in your function lies in assumption that j holds pivot location in subcalls:
qsort(arr, m, j+1); //sort left sub array
qsort(arr, j+1, n); //sort right sub array
Actually, j is set again and again equal to i in your main for loop. If last element is equal or greater than pivot, you end up with j=n-1, the you call qsort(arr, n, n) and first lines check is passed (sic!), because n-n != 1.
To fix this you should do two things:
1) find pivot location directly after rearrange:
for (int i = m; i < n; i++)
if (p == arr[i])
{
j = i;
break;
}
or initialize it in different variable, update after this line:
arr[j] = t; //pivot is at j and j+1
and update recursive calls to use new variable instead of j
2) make a more bulletproof check in the beginning of your function:
if (n - m <= 1)
the latter will be enough to get some result, but it will be much less effective than your current idea, falling down to probably O(N^3) in worst case.
I am getting two errors in implementing the algorithm from pseudocode:
One of my problems is int L[n1+1]; error: needs to be a constant; cannot allocate constant size 0. The only way to run this is to make the size a number like 10. I may be implementing the psuedocode wrong that is why I included the statement above that. This may be the cause of my next problem.
My other problem is I am printing only one line of code unsorted. My print function is flawless and works for all of the sorting programs. I believe the MERGE function is only running once. I posted the output of the Sort at the bottom.
I have a random number generator for the array A, from 0 to RAND_MAX.
Initial call is MERGESORT(A,1,n);
void MERGE(int *A, int p, int q, int r)
{
int n1 = q-(p+1);
int n2 = r-q;
//psuedocode states, let L[1..n1+1] & R[1..n1+1] be new arrays
int L[n1+1];
int R[n2+1];
for(int i=1; i<n1;i++)
{
L[i]=A[p+(i-1)];
}
for(int j=1; j<n2; j++)
{
R[j] = A[q+j];
}
L[n1+1]=NULL; //sentinel
R[n2+1]=NULL; //sentinel
int i=1;
int j=1;
for (int k=p; k<r; k++)
{
if(L[i]<=R[j])
{
A[k]=L[i];
i=i+1;
}
else
{
A[k]=R[j];
j=j+1;
}
}
}
void MERGESORT(int *A,int p, int r)
{
if (p<r)
{
int q=floor((p+r)/2);
MERGESORT(A,p,q);
MERGESORT(A,q+1,r);
MERGE(A,p,q,r);
}
}
With int L[10]; and my A[10]; my output is:
Sort: 7474 28268 32506 13774 14411
Press any key to continue . . .
If someone could just assist in the two problems, I more than likely will get it to work.
You are failing to detect the end of your merge arrays:
for (int k=p; k<r; k++)
{
// You need to check that i/j are still in range.
// otherwise the following test are not valid.
if ((i < n1) && (j < n2))
{
if(L[i]<=R[j])
{
A[k]=L[i];
i=i+1;
}
else
{
A[k]=R[j];
j=j+1;
}
}
else
{ /* More work here */
}
Other comments:
Identifiers that are all capitol MERGE MERGESORT are generally reserved for macros. If you use them you are likely to hit problems. Prefer function names of mixed case.
You can simulate arrays with vector:
// Simulate L[1..n1+1]
minI = 1;
maxI = n1-1;
std::vector<int> const L(A+(minI-1), A+(maxI-1));
Arrays in C++ are zero indexed. You seem to be having off by one errors (especially in accessing the end of the array). I would advice you to start the count at 0 rather than 1. Most C++ code is written in terms of iterators from [begining..1PastEnd). I think you will find your algorithm easier to implement if you adapt that style.
There are several issues with your code, I've pointed them out in comments. This is a solution closest to your code, and it's far from best. Consider using C++ containers, like std::vector for example. Naming is at least disputable, and of course merge sort should be implemented as an in place algorithm.
//L and R are auxiliary arrays
//preallocated with (inputSize/2 + 1) constant size
void MERGE(int *A, int p, int q, int r, int* L, int* R)
{
if (p > q || q > r)
{
return;
}
int n1 = q - p + 1;
int n2 = r - q;
// note 0-based indices
int i = 0;
int j = 0;
for(;i < n1;i++)
{
L[i] = A[p + i];
}
for(;j < n2;j++)
{
R[j] = A[q + j + 1]; //+1 because p + n1 - 1 == q + 0
}
//again - note 0-based indices
i = 0;
j = 0;
for (int k = p; k <= r; ++k)
{
// The most important fix - in your code you didn't check
// for left/right array bounds at all.
// Sentinel values aren't needed - size is known
if(i < n1 && (j >= n2 || L[i] <= R[j]))
{
A[k] = L[i];
++i;
}
else if (j < n2)
{
A[k] = R[j];
++j;
}
}
}
void MERGESORT(int* A, int p, int r, int* L, int* R)
{
if (p < r)
{
int q = (p + r) / 2; //floor was redundant
MERGESORT(A, p, q, L, R);
MERGESORT(A, q+1, r, L, R);
MERGE(A, p, q, r, L, R);
}
}
void MERGESORT(int* A, int size)
{
int*L = new int[size/2 + 1]; //preallocate auxiliary arrays
int*R = new int[size/2 + 1]; //size/2 + 1 is what will be needed at most
MERGESORT(A, 0, size - 1, L, R);
delete L;
delete R;
}
int main()
{
int A[5]{ 7474, 28268, 32506, 13774, 14411 };
MERGESORT(A, 5);
for (int i = 0;i < 5;++i)
{
std::cout << A[i] << std::endl;
}
return 0;
}
Output:
7474
13774
14411
28268
32506
Credit goes also to DyP for spotting all the mistakes in the previous version :)