I am trying to implement merge sort for my algorithm analysis class and every time I run it there is a segmentation fault. I think the problem is when i split the vector in the merge_sort function but I cannot find the problem. Help would be really appreciated guys.
template <typename T>
std::vector<int> merge(std::vector<T>& A,std::vector<T>& B)
{
int a_size = A.size();
int b_size = B.size();
std::vector<int> C(a_size+b_size,0);
//int *c = new int[b_size+a_size];
int i =0,j =0,k=0;
while(i < a_size && j < b_size)
{
if(A[i]<B[j])
{
C[k] = A[i];
k++;
i++;
}
else
{
C[k] = B[j];
k++;
j++;
if(i!=a_size)
{
for(;i<a_size;i++,k++)
{
//copy rest of a to c
C[k] = A[i];
}
}
if(j != b_size)
{
for(;j<b_size;k++,j++)
{
//copy the rest of b to c
C[k] = B[j];
}
}
}
}
return C;
}
// Merge sort implementation
template <typename T>
void merge_sort(std::vector<T>& vector)
{
// TODO implement merge sort
int vector_size = vector.size();
int big_vector_index = 0;
int half_size = (int)vector_size/2;
int remainder = vector_size%2;
std::vector<int> left(half_size,0);
std::vector<int> right(half_size+remainder,0);
for(int l = 0;big_vector_index<half_size;l++,big_vector_index++)
{
left[l] = vector[big_vector_index];
}
for(int m = 0;big_vector_index<vector_size;m++,big_vector_index++)
{
right[m] = vector[big_vector_index];
}
big_vector_index = 0;
merge_sort(left);
merge_sort(right);
vector = merge(left,right);
}
I took a look at your code, and the majority of it is correct from my testing. I don't want to do your coursework for you but maybe a couple of hints in the right direction will help.
For your original question about the segfault that you got, PaulMcKenzie, Jim Lewis, and Tahlil are right, merge_sort() needs a base condition (base case) to check whether or not the recursion should continue, so it doesn't run forever and/or until your computer runs out of memory (which is what is happening in your case). In general, any recursive function should have a base case.
Also, you should take a look at your merge function as well. It has all the parts of a correct merge function, but some parts of it run a bit earlier/more often than you want them too. I don't want to give too much away since it's for class, but if you fix the segfault problem and are still getting strange answers, take a look at it.
Related
I'm trying to implement a sorting program of numbers, but am getting the following error:
I was able to compile and work the code on an online c++ compiler, but when I must run it via the terminal so after attempting to do so, it won't compile anymore. There's actually nothing wrong with the code itself, since they're just warnings. But I would like to know how to fix them all, please!
The errors come from these parts of my code:
void sort()
{
int i, j;
for (i = 0; i < storage.size()-1; i++)
{
for (j = 0; j < storage.size()-i-1; j++)
{
if (storage[j] > storage[j+1]) // swap the values
{
int temp = storage[j];
storage[j] = storage[j+1];
storage[j+1] = temp;
}
}
}
}
void print()
{
for(int i = 0; i < storage.size(); i++)
cout<<storage[i]<<" ";
cout<<endl;
}
vector<int> getList()
{
return storage;
}
void setList(vector<int> list)
{
storage = list;
}
};
void quickSort(int start, int end)
{
if (start < end)
{
int part = partition(start, end);
quickSort(start, part - 1);
quickSort(start + 1, end);
}
}
void sort()
{
quickSort(0, storage.size() - 1);
}
void print()
{
for(int i = 0; i < storage.size(); i++)
cout<<storage[i]<<" ";
cout<<endl;
}
Any help will be much appreciated. Thank you!
would like to know how to fix them all, please!
The diagnostic says that you are comparing numbers of different signedness. You can fix that by not comparing numbers of different signedness. You can go with using signed type on both sides or unsigned type on both sides.
Aside from the warning, storage.size()-1 is a dangerous operation unless you first enforce that the container is non-empty. If you subtract from a unsigned zero, you get a very large unsigned value. That is not bad by itself, but when you eventually use that large value as subscript, you get undefined behaviour. Simple solution to this is to add +1 to both sides of the comparison: i+1 < storage.size().
I'm trying to fix a SIGSEGV error in my program. I am not able to locate the site of error. The program compiles successfully in Xcode but does not provide me the results.
The goal of the program is to check whether the same element occurs in three separate arrays and return the element if it is more than 2 arrays.
#include <iostream>
using namespace std;
int main()
{
int i = 0 ,j = 0,k = 0;
int a[5]={23,30,42,57,90};
int b[6]={21,23,35,57,90,92};
int c[5]={21,23,30,57,90};
while(i< 5 or j< 6 or k< 5)
{
int current_a = 0;
int current_b = 0;
int current_c = 0;
{ if (i<5) {
current_a = a[i];
} else
{
;;
}
if (j<6)
{
current_b = b[j];
} else
{
;;
}
if (k<5)
{
current_c= c[k];
} else
{
;;
}
}
int minvalue = min((current_a,current_b),current_c);
int countoo = 0;
if (minvalue==current_a)
{
countoo += 1;
i++;
}
if (minvalue==current_b)
{
countoo +=1;
j++;
}
if (minvalue==current_c)
{
countoo += 1;
k++;
}
if (countoo >=2)
{
cout<< minvalue;
}
}
}
I am not getting any output for the code.
This is surely not doing what you want
int minvalue = min((current_a,current_b),current_c);
If min() is defined meaningfully (you really should provide an MCVE for a question like this), you want
int minvalue = min(min(current_a,current_b),current_c);
This will result in the minimum of the minimum of (a and b) and c, i.e. the minimum of all three, instead of the minimum of b and c. The comma operator , is important to understand this.
This seems to be a flag/counter to make a note across loop executions or count something
int countoo = 0;
It can however not work if you define the variable inside the loop.
You need to move that line BEFORE the while.
With this line you do not prevent the indexes to leave the size of the arrays,
that is very likely the source for the segfault.
while(i< 5 or j< 6 or k< 5)
In order to prevent segfaults, make sure that ALL indexes stay small enough,
instead of only at least one.
while(i< 5 && j< 6 && k< 5)
(By the way I initially seriously doubted that or can compile. I thought
with a macro for or it could, but I do not see that. It could be a new operator in a recent C++ standard update which I missed...
And it turns out that it is the case. I learned something here.)
This should fix the segfault.
To achieve the goal of the code I think you need to spend some additional effort on the algorithm. I do not see the code being related to the goal.
I am trying to send a vector into a bubbleSort function to organize numbers from max to min as they are produced one by one, but I am getting the "C2100: Illegal indirection" warning. Can someone please help me out?
private: void bubbleSort(vector<int> &matrixPtr)
{
int temp;
int numLength = *matrixPtr.size( );//length of vector
for (int i = 1; (i <= numLength);i++)
{
for (int j=0; j < (numLength -1); j++)
{
if (*matrixPtr[j+1] > *matrixPtr[j])
{
temp = *matrixPtr[j];//Swap elements
*matrixPtr[j] = *matrixPtr[j+1];
*matrixPtr[j+1] = temp;
}
}
}
}
The bubbleSort is drawn from another function ahead of it:
bubbleSort(&output);//pass to bubble sort
for (int rows=0;rows<creation->getZeroRows();rows++)
{
for (int cols=0;cols<creation->getCols();cols++)
{
txt_DisplayRowSum->Text= String::Concat(txt_DisplayRowSum->Text, (*creation->zeroArrayPtr)[rows][cols]," ");
}
txt_DisplayRowSum->Text+=" \n";
}
Thank you for your help in advance
You are incorrectly using references.
Instead of *matrixPtr.size( ) you need matrixPtr.size(), and everywhere else in the function you do not need the * when referring to matrixPtr. Also, when passing the vector to the function, you should pass just output and not &output.
You should not and can not use references like pointers. While similar, they're different in several important ways. I also recommend this question for a good summary of those differences.
So I have the following code and I need to derive the execution time growth rate, however I have no idea where to start. My question is, how do I go about doing this? Any help would be appreciated.
Thank you.
// function to merge two sorted arrays
int merge (int smax, char sArray[], int tmax, char tArray[], char target[])
{
int m, s, t;
for (m = s = t = 0; s < smax && t < tmax; m++)
{
if (sArray[s] <= tArray[t])
{
target[m] = sArray[s];
s++;
}
else
{
target[m] = tArray[t];
t++;
}
}
int compCount = m;
for (; s < smax; m++)
{
target[m] = sArray[s++];
}
for (; t < tmax; m++)
{
target[m] = tArray[t++];
}
return compCount;
}
It's actually very simple.
Look, the first for loop increases either s or t at each iteration, so it's O(smax + tmax). The second loop is obviously O(smax), the third is O(tmax). Altogether we get O(smax + tmax).
(There exist some cleverer ways to prove, but I've intentionally left them out.)
All loops are bounded in number of iterations by (smax + tmax). So you could say the algorithm is O( max(smax,tmax) ) or O( smax +tmax).
What could be the best algorithm for "Merge Sort" in C++ where the memory must be used "most effectively"? I just know the standard way to do this, but that's not the most effective way how to use the memory.
This is the only variant which I know:
#include <iostream>
using namespace std;
int main() {
int arr1[20]= {0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int arr2[14]= {0,23,25,27,29,31,33,35,37,39,40,41,42,43};
int arr3[34];
int indexA=0, indexB=0, indexC=0;
while((indexA<20) && (indexB<14)) {
if(arr1[indexA] < arr2[indexB]) {
arr3[indexC] = arr1[indexA];
indexA++;
}
else {
arr3[indexC] = arr2[indexB];
indexB++;
}
indexC++;
}
while(indexA<20) {
arr3[indexC] = arr1[indexA];
indexA++;
indexC++;
}
while(indexB<14) {
arr3[indexC] = arr2[indexB];
indexB++;
indexC++;
}
for (int i=0; i<34; i++)
cout << arr3[i] << " ";
return 0;
}
Can anyone please advise me a better algorithm for "Merge Sort" which uses the memory in "more effective" way? It can also not be with arrays.
Thank You very much!
The usual problem with merge sort is that for every recursion, you end up using a whole new piece of memory. This turns out to need O(N*log(n)) memory. It turns out that if you're a bit more clever, you can do this with linear O(N) memory. Just don't make new arrays, and swap the elements as needed around within the original one.
By the Algorithm nature - Merge Sort need an additional space of the Same Size of the Array you are trying to Sort.
A kind of answer to your question. The book "Data Structures & Algorithms in Java - Second Edition by Robert Lafore" has an example that used only an duplicate array of the same size instead of creating multiple sub array. You can find the program #
http://homepage.cs.uiowa.edu/~sriram/21/fall07/code/mergeSort.java
The following example is just to explain the mergesort in simple way.
import java.util.Arrays;
import java.util.Random;
public class SimpleMergeSort {
void mergeSort(int [] arr)
{
if( arr.length <= 1)
return;
int mid = arr.length / 2;
int [] left = Arrays.copyOfRange(arr, 0, mid);
int [] right = Arrays.copyOfRange(arr, mid, arr.length);
mergeSort(left);
mergeSort(right);
merge(left,right,arr);
}
void merge(int [] left, int [] right, int[] arr)
{
int arrIndex = 0;
int leftIndex = 0;
int rightIndex = 0;
//both left and right are not empty
while( leftIndex < left.length && rightIndex < right.length)
{
if( left[leftIndex] < right[rightIndex])
{
arr[arrIndex++] = left[leftIndex++];
}
else
{
arr[arrIndex++] = right[rightIndex++];
}
}
//if left still has some content
while(leftIndex < left.length)
{
arr[arrIndex++] = left[leftIndex++];
}
//if right still has some content
while(rightIndex < right.length)
{
arr[arrIndex++] = right[rightIndex++];
}
}
public static void main(String[] args) {
int [] array = new int[10];
Random random = new Random();
for(int i=0; i<array.length; i++)
{
array[i] = random.nextInt(1000);
}
System.out.println(Arrays.toString(array));
SimpleMergeSort sort = new SimpleMergeSort();
sort.mergeSort(array);
System.out.println(Arrays.toString(array));
}
}
instead of using merge and sorting in the main u could have used recursion which would have decreased your load in manually computing and dividing the array into two parts enter code heremid =beg+end/2;a[beg,.....,end] //so
a1[beg,...mid] //and
a2[]mid+1,....end]then call the recursion functions check the base case carefullyif(big