For some reason, my program keeps crashing while it's in this mergeSort function which has a purpose just to merge sort an array of data. In this case, I'm using an array of strings.
Here is the merge sort function code:
template <class T>
void Metrics<T>::mergeSort(T *arr, int n)
{
if ( n < 10 )
{
insertionSort(arr,n);
return;
}
int mid = n / 2;
int mid2 = n - mid;
T *Left = new T[mid];
T *Right = new T[mid2];
for ( int i = 0; i < mid; i++ )
{
Left[i] = arr[i];
}
for ( int i = 0; i < mid2; i++ )
{
Right[i] = arr[mid+i];
}
mergeSort(Left, mid);
mergeSort(Right,mid);
merge(Left,mid,Right,mid2,arr);
delete Left;
delete Right;
}
and Here is the merge function used in the mergeSort function:
template <class T>
void Metrics<T>::merge(T *a, int numA, T *b, int numB, T *c)
{
int i, j, k;
i = j = k = 0;
while ( i < numA && j < numB )
{
if (a[i] <= b[j])
{
c[k] = a[i];
i++;
k++;
}
else
{
c[k] = b[j];
j++;
k++;
}
}
while ( i < numA )
{
c[k] = a[i];
i++;
k++;
}
while ( j < numB )
{
c[k] = b[j];
j++;
k++;
}
}
The initial parameters I'm sending into the mergeSort function is just an array of strings, and the int n is 36. Oh and by the way, the insertion sort code is this:
template <class T>
void Metrics<T>::insertionSort(T *arr, int n)
{
for ( int i = 1; i < n; i++ )
{
int j = i;
while ( j > 0 && arr[j] < arr[j-1] )
{
T temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
j--;
}
}
}
I'm pretty sure it has to do with the fact that I'm sending in an array of strings into the function. It works when it's just with integers and characters though. Thanks!
EDIT:: After looking into it a little bit, I think it crashes on the "Delete Left" and "Delete Right" code on the bottom of mergeSort. Is there a reason for that? How can I fix it? Is that why it's crashing?
You should be using delete [] Left and delete [] Right to match the new [] calls.
Also you call to mergeSort(Right,mid); should be mergeSort(Right,mid2); but I don't think that would cause a crash, just a non-sorted item when n was odd.
Related
When I compile, it gives error of read access violation. Other stack overflow posts says this is due to an infinite loop. I also saw that the value goes to a very large negative number. My guess is that it is because list[-1], but I do not know how to change it so it does not go past list[0].
Insertion sort code
void insertion_sort(int list[], int length) {
for (int i = 1; i < length; i++) {
for (int j = i; (j > 0) && (list[j] < list[j - 1]); j--) {
swap(list, list[j - 1], list[j]);
}
}
}
Swap function code
void swap(int list[], int & src, int & dest){
int temp = list[src];
list[src] = list[dest];
list[dest] = temp;
}
You are using the values of your sort as an index in your swap. Keep it simple.
This works.
void insertion_sort(int list[], int length) {
for (int i = 1; i < length; i++) {
for (int j = i; (j > 0) && (list[j] < list[j - 1]); j--) {
std::swap( list[j - 1], list[j] );
}
}
}
int main( )
{
int arr[ 100 ];
for( size_t i= 0; i < 100; ++i )
arr[ i ]= std::rand( );
insertion_sort( arr, 100 );
return 0;
}
Added:
As this looks like a class exercise. What you want to notice is that std::swap has no idea that your list exists. All it wants to know is what values you want to swap. So if you can't use the standard library, write your swap like the standard.
void insertion_sort(int list[], int length) {
for (int i = 1; i < length; i++) {
j = i;
while(j > 0 && list[j - 1] > list[j]){
swap(list, list[j], list[j-1]);
j--;
}
}
This should work for sorting least to greatest. The while loop does the job of checking if it needs to be swapped and checks the already "sorted" positions in the array if it needs to be swapped again.
Happy Coding.
I try to implement the merge sort algorithm and I get a segmentation fault. Why? The error seems to be in the MergeSort function. The merge sort function (on the 2nd call) when should check only an array of 4 numbers (the length should be 4) shows the length = 27. Why? (tested on an array with 8 elements)
#include<iostream>
using namespace std;
int n, A[1000];
void citire(int lungime) {
for (int i = 0; i < lungime; i++) cin >> A[i];
}
void afisare(int lungime) {
for (int i = 0; i < lungime; i++)
cout << A[i] << " ";
cout << '\n';
}
int lungime(int A[]) {
int i = 0;
while (A[i]) i++;
return i;
}
void Merge(int L[], int R[], int A[]) {
int nL = lungime(L);
int nR = lungime(R);
int i = 0, j = 0, k = 0;
while (i < nL && j < nR) {
if (L[i] <= R[j]) {
A[k] = L[i];
i++;
}
else {
A[k] = R[j];
j++;
}
k++;
}
while (i < nL) {
A[k] = L[i];
i++;
k++;
}
while (j < nR) {
A[k] = R[j];
j++;
k++;
}
}
void MergeSort(int A[]) {
int n1 = lungime(A);
if (n1 < 2) return;
else
{
int mid = (int)n1 / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++)
L[i] = A[i];
for (int i = mid; i < n; i++)
R[i - mid] = A[i];
MergeSort(L);
MergeSort(R);
Merge(L, R, A);
}
}
int main() {
cin >> n;
citire(n);
MergeSort(A);
afisare(n);
return 0;
}
Changes made in this example. A[], L[], R[] are allocated using new. A[] is passed as a parameter. L[] and R[] are allocated in Merge(). Size and/or indices passed as parameters, and lungime() is no longer used to get size. Other changes noted in comments.
#include<iostream>
using namespace std;
void citire(int A[], int lungime) { // A is parameter
for (int i = 0; i < lungime; i++) cin >> A[i];
}
void afisare(int A[], int lungime) { // A is parameter
for (int i = 0; i < lungime; i++)
cout << A[i] << " ";
cout << '\n';
}
// A, low, mid, end are parameters
// L and R allocated here
void Merge(int A[], int low, int mid, int end) {
int sizeL = mid-low;
int sizeR = end-mid;
int *L = new int[sizeL];
int *R = new int[sizeR];
for(int i = 0; i < sizeL; i++)
L[i] = A[low+i]; // A[low+i]
for(int i = 0; i < sizeR; i++)
R[i] = A[mid+i]; // A[mid+i]
int i = 0, j = 0, k = low; // k = low
while (i < sizeL && j < sizeR) {
if (L[i] <= R[j]) {
A[k] = L[i];
i++;
}
else {
A[k] = R[j];
j++;
}
k++;
}
while (i < sizeL) {
A[k] = L[i];
i++;
k++;
}
while (j < sizeR) {
A[k] = R[j];
j++;
k++;
}
delete[] R;
delete[] L;
}
// A, low, end are parameters
void MergeSort(int A[], int low, int end) {
int sizeA = end - low;
if(sizeA < 2)
return;
int mid = low + (sizeA / 2); // mid = low + ...
MergeSort(A, low, mid);
MergeSort(A, mid, end);
Merge(A, low, mid, end);
}
int main() {
int n;
cin >> n;
int *A = new int[n]; // A is allocated
citire(A, n); // A, n are parameters
MergeSort(A, 0, n); // A, 0, n are parameters
afisare(A, n); // A, n are parameters
delete[] A;
return 0;
}
"The lungime function is the length of the string and this function works good. I've tested it on different arrays".
Well, this is purely accidental; uninitialized memory can contain zeros, and provide the array terminator by accident.
If you want to keep the current design, you should:
initialize A to zeros
make sure that there are no more than 999 elements in the input stream,
that no element has the value zero, as zero is reserved, and used as terminator, and
define L and R (in MergeSort) one element longer, and initialize the last element to zero.
Unless there are overwhelming reasons for a "roll your own" sort solution, you might have a look at prefab sort support. The vector class in C++ offers just that.
I'm new to programming. I just recently started studying algorithms.
My code should just carry out the merge sort procedure but it has some errors although it builds correctly.
My code takes input then stops working.
It shows this error:
#include<iostream>
using namespace std;
#define size 10
class mergesort {
public:
mergesort(){}
void merge(int a[]) {
int mid = 5;
if (size < 2) return;
int left[size]; int right[size];
for (int i = 0; i < mid; i++) {
left[i] = a[i];
}
for (int j = mid; j < size-1; j++) {
right[j-mid] = a[j];
}
merge(left);
merge(right);
sort(left, right, a, mid, size-mid);
}
void sort(int left[], int right[], int a[], int L, int R) {
int i = 0; int j = 0; int k = 0;
while (i < L && j < R) {
if (left[i] <= right[j])
{
a[k] = left[i];
k++; i++;
}
else if (right[j] < left[i]) {
a[k] = right[j];
k++; j++;
}
}
while (i < L) {
a[k] = left[i];
k++; i++;
}
while (i < R) {
a[k] = right[j];
k++; j++;
}
}
};
void main() {
mergesort m;
int a[size];
cout << "Enter the elements:" << endl;
for (int i = 0; i < size; i++) {
cin >> a[size];
}
m.merge(a);
}
The stack overflow error is due to an infinite recursion "loop".
merge() needs two more parameters. In this example, I allocated from stack using _alloca(), so no free is needed. This will only work for arrays small enough to not overflow the stack. The alternative is to use malloc() and free().
void merge(int a[], int lo, int hi) // hi is end == last + 1
{
if((hi - lo) < 2)
return;
int mid = (lo+hi)/2;
int *left = _alloca((mid - lo)*sizeof(int)); // alloc from stack
int *right = _alloca((hi - mid)*sizeof(int)); // alloc from stack
for (int i = lo; i < mid; i++)
left[i-lo] = a[i];
for (int i = mid; i < hi; i++)
right[i-mid] = a[i];
merge(left, lo, mid);
merge(right, mid, hi);
sort(left, right, a, mid-lo, hi-mid);
}
}
The last while in sort() needs to use j instead of i:
while (j < R) { // use j here
a[k] = right[j];
k++; j++;
}
Alternative approach - use a one time helper function to do a one time allocation of a second array the same size as a[], perhaps calling it b[], and use the same indexing for b[] as a[] when doing the splitting and merging. b[] would be passed as a parameter to both merge() and sort(), and would be used instead of left[] and right[].
The names are confusing, merge() is really a "sort", and sort() is really a "merge".
I have the following code.. The method should work but I'm having trouble passing the vector to a function. I searched around and found that vector can be passed as 'references' or 'values' and I tried both, but they didn't seem to work. Am I calling the method incorrectly or passing the vector in a wrong way? Either ways, what can I do to fix this? Thanks! :)
//insertion sort method
#include <iostream>
#include <vector>
using namespace std;
void insertionSort(int arr[], int n){
for(int i = 0; i < n; i++){
int temp = arr[i]; // element adjacent to left sorted array
int j = i - 1;
while(temp > arr[j] && j != 0){
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
}
int main(){
int n, temp;
cin >> n;
vector <int> arr;
for(int i = 0; i < n; i++){
cin >> temp;
arr.push_back(temp);
}
insertionSort(arr, n);
for(int i = 0; i < n; i++)
cout << arr[i] << " ";
return 0;
}
The first parameter of the insertionSort(int arr[], int n) method is wrong.
You also processed the arr incorrectly. At first iteration, int j = 0 - 1 = -1; which is unexpected/ out of bound.
Please try this :
void insertionSort(vector <int> &arr, int n){
int i, j, temp;
for (i = 1; i < n; i++)
{
temp = arr[i];
j = i - 1;
while ((j >= 0) && (temp<arr[j]))
{
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = temp;
}
}
Thanks !!!
i'm currently working on iterative version of mergesort, but i've encountered a problem. The program crashes when there are specific sizes of array's like 34,35,36 or 100(just few examples) and it works for the rest(fe works for powers of 2). I've ran some tests and debugged it, and the problem seems to be with the ranges of my iterations/left,right halves of mergesort, but i can't find it. I'll be thankful for your help.
Code:
int * loadArray(int size){ //i input size of array and it assigns random numbers
int *array = new int[size];
srand( time( NULL ) );
for( int i = 0; i < size; i++ )
array[i]=rand()%100;
return array;
}
void merge(int arr[], int left, int middle, int right)
{
int i, j, k; //iterators
int n1 = middle-left + 1; //indexes
int n2 = right-middle; //indexes
int Left[n1], Right[n2]; //arrays holding halves
for (i = 0; i < n1; i++)
Left[i] = arr[left + i];//assigning values to left half
for (j = 0; j < n2; j++)
Right[j] = arr[middle + 1+ j];//assigning values to right half
i = 0;
j = 0;
k = left;
while (i < n1 && j < n2) //comparing and merging
{
if (Left[i] <= Right[j])
{
arr[k] = Left[i];
i++;
}
else
{
arr[k] = Right[j];
j++;
}
k++;
}
while (i < n1) //leftovers
{
arr[k] = Left[i];
i++;
k++;
}
while (j < n2) //leftovers
{
arr[k] = Right[j];
j++;
k++;
}
}
void mergeSortIter(int array[], int size) //the function which is being called and handles division of the array
{
double startTime = clock(); //start measuring time
int i;
int left_start;
for (i=1; i<=size-1; i = 2*i)
{
for (left_start=0; left_start<size-1; left_start += 2*i)
{
int mid = left_start + i - 1;
int right_end = min(left_start + 2*i - 1, size-1);
merge(array, left_start, mid, right_end);
}
//showArray(array,size);
}
cout << double( clock() - startTime ) / (double)CLOCKS_PER_SEC<< " seconds." << endl; //output the time measured
}