double recursion segmentation fault c++ - c++

I've recently written this quicksort sorting algorithm. After compiling I get a "segmentation fault (core dumped)". I debugged it and it turned out that line 25 causes the problem:
v2 = quicksort(v2);
However, I do not know why I get a the "core dumped", as I have no idea what's the problem with this line.
Here's my code:
#include <iostream>
#include <vector>
#include <random>
using namespace std;
vector <float> quicksort(vector <float> Vec)
{
if(Vec.size() > 1)
{
float pivot = Vec[(Vec.size())/2-1];
vector <float> v1, v2;
vector <float> V;
for(unsigned int i = 0; i < Vec.size(); i++)
{
if(Vec[i] >= pivot)
v2.push_back(Vec[i]);
else
v1.push_back(Vec[i]);
}
v1 = quicksort(v1);
v2 = quicksort(v2);
//after debuggung, I found out that the line above causes the "segmentation fault (core dumped)" (line 25)
for(unsigned int i = 0; i < v1.size(); i++)
V.push_back(v1[i]);
for(unsigned int i = 0; i < v2.size(); i++)
V.push_back(v2[i]);
return V;
}
else
{
return Vec;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
vector <float> v;
for(int i = 0; i < 100; i++)
{
v.push_back(rand() % 100);
cout << v[i] << " ";
}
v = quicksort(v);
for(int i = 0; i < 100; i++)
{
cout << v[i] << " ";
}
return 0;
}
Thanks for the help.

First of all, to get a totally random number using rand() you need to seed the number generator. To do this you include the "time.h" library and then write: srand (time(NULL));
Secondly, your quicksort takes two parameters, a vector named Vec and an int f, that isn't used for anything. Take int f of the function's parameters.
Thirdly, the problem is that an infinite loop is happening in this part of the code (lines 17 to 23):
for(unsigned int i = 0; i < Vec.size(); i++){
if(Vec[i] >= pivot)
v2.push_back(Vec[i]);
else
v1.push_back(Vec[i]);
}
Imagine that our Vec vector is {2, 3} (this were the actual values, because we didn't seed the random number generation).
What's happening is that we have our pivot = 2, and then we are saying that if Vec[0], which is 2, is bigger or equal than the pivot, we add Vec[0] to v2, and then the same for Vec[1], which is 3.
Then this loops infinitely, because then you say v2 = quicksort(v2);. That will make Vec = v2. And that means that it will never get smaller, because, again, Vec is {2, 3}, and therefore our pivot = 2.

It goes in stack overflow.
If the pivot is the maximum number of the vector Vec it has to be dragged from Vinf into Vsup.
#include <iostream>
#include <vector>
#include <random>
using namespace std;
vector <float> quicksort(vector <float> Vec) { //the int f was never used un the function
if (Vec.size() > 1){
vector <float> Vinf, Vsup, Vtmp;
Vinf.push_back(Vec[(Vec.size()) / 2 - 1]);
float pivot = Vinf[0];
Vec.erase(Vec.begin() + Vec.size() / 2 - 1);
for (unsigned int i = 0; i < Vec.size(); i++)
Vec[i] > pivot ? Vsup.push_back(Vec[i]) : Vinf.push_back(Vec[i]);
if (Vinf.size() == Vec.size() + 1) {
Vsup.push_back(pivot);
Vinf.erase(Vinf.begin());
}
Vinf = quicksort(Vinf);
Vsup = quicksort(Vsup);
for (unsigned int i = 0; i < Vinf.size(); Vtmp.push_back(Vinf[i++]));
for (unsigned int i = 0; i < Vsup.size(); Vtmp.push_back(Vsup[i++]));
return Vtmp;
}
else
return Vec;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
vector <float> v;
for (int i = 0; i < 100; cout << v[i++] << " ")
v.push_back(rand() % 100);
cout << endl;
v = quicksort(v);
for (int i = 0; i < v.size(); cout << v[i++] << " ");
return 0;
}

Related

Find the missing numbers in the given array

Implement a function which takes an array of numbers from 1 to 10 and returns the numbers from 1 to 10 which are missing. examples input: [5,2,6] output: [1,3,4,7,8,9,10]
C++ program for the above approach:
#include <bits/stdc++.h>
using namespace std;
// Function to find the missing elements
void printMissingElements(int arr[], int N)
{
// Initialize diff
int diff = arr[0] - 0;
for (int i = 0; i < N; i++) {
// Check if diff and arr[i]-i
// both are equal or not
if (arr[i] - i != diff) {
// Loop for consecutive
// missing elements
while (diff < arr[i] - i) {
cout << i + diff << " ";
diff++;
}
}
}
}
Driver Code
int main()
{
// Given array arr[]
int arr[] = { 5,2,6 };
int N = sizeof(arr) / sizeof(int);
// Function Call
printMissingElements(arr, N);
return 0;
}
How to solve this question for the given input?
First of all "plzz" is not an English world. Second, the question is already there, no need to keep writing in comments "if anyone knows try to help me".
Then learn standard headers: Why should I not #include <bits/stdc++.h>?
Then learn Why is "using namespace std;" considered bad practice?
Then read the text of the problem: "Implement a function which takes an array of numbers from 1 to 10 and returns the numbers from 1 to 10 which are missing. examples input: [5,2,6] output: [1,3,4,7,8,9,10]"
You need to "return the numbers from 1 to 10 which are missing."
I suggest that you really use C++ and get std::vector into your toolbox. Then you can leverage algorithms and std::find is ready for you.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
std::vector<int> missingElements(const std::vector<int> v)
{
std::vector<int> missing;
for (int i = 1; i <= 10; ++i) {
if (find(v.begin(), v.end(), i) == v.end()) {
missing.push_back(i);
}
}
return missing;
}
int main()
{
std::vector<int> arr = { 5, 2, 6 };
std::vector<int> m = missingElements(arr);
copy(m.begin(), m.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
return 0;
}
If you want to do something with lower computational complexity you can have an already filled vector and then mark for removal the elements found. Then it's a good chance to learn the erase–remove idiom:
std::vector<int> missingElements(const std::vector<int> v)
{
std::vector<int> m = { -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (const auto& x: v) {
m[x] = -1;
}
m.erase(remove(m.begin(), m.end(), -1), m.end());
return m;
}
By this approach we are using space to reduce execution time. Here the time complexity is O(N) where N is the no of elements given in the array and space complexity is O(1) i.e 10' .
#include<iostream>
void printMissingElements(int arr[], int n){
// Using 1D dp to solve this
int dp[11] = {0};
for(int i = 0; i < n; i++){
dp[arr[i]] = 1;
}
// Traverse through dp list and check for
// non set indexes
for(int i = 1; i <= 10; i++){
if (dp[i] != 1) std::cout << i << " ";
}
}
int main() {
int arr[] = {5,2,6};
int n = sizeof(arr) / sizeof(int);
printMissingElements(arr, n);
}
void printMissingElements(int arr[], int n,int low, int high)
{
bool range[high - low + 1] = { false };
for (int i = 0; i < n; i++) {
if (low <= arr[i] && arr[i] <= high)
range[arr[i] - low] = true;
}
for (int x = 0; x <= high - low; x++) {
if (range[x] == false)
std:: cout << low + x << " ";
}
}
int main()
{
int arr[] = { 5,2,6,6,6,6,8,10 };
int n = sizeof(arr) / sizeof(arr[0]);
int low = 1, high = 10;
printMissingElements(arr, n, low, high);
return 0;
}
I think this will work:
vector<int> missingnumbers(vector<int> A, int N)
{ vector<int> v;
for(int i=1;i<=10;i++)
v.push_back(i);
sort(A.begin(),A.end());
int j=0;
while(j<v.size()) {
if(binary_search(A.begin(),A.end(),v[j]))
v.erase(v.begin()+j);
else
j++;
}
return v;
}

Set of Pairs program in C++

I am making a set of pairs of Max and Min elements of Every Subset in an Array.But its giving me these errors. And at last I need Size of set.
(Edited with some suggestions)
In function 'int main()':
27:12: error: 'max_element' was not declared in this scope
27:12: note: suggested alternative: 'max_align_t'
28:12: error: 'min_element' was not declared in this scopeIn function 'int main()':
Code:
#include <iostream>
#include <set>
#include <vector>
#include <utility>
typedef std::pair<int,int> pairs;
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, max, min;
set<pairs> s;
cin >> n;
int a[n];
for(int i=0;i<n;i++) {
cin >> a[i];
}
for(int i=0;i<n;i++) {
for(int j=i;j<n;j++) {
vector<int> v;
v.push_back(a[j]);
if(v.size() > 1) {
max = *max_element(v.begin(),v.end());
min = *min_element(v.begin(),v.end());
pairs p1 = make_pair(max, min);
s.insert(p1);
max = 0;
min = 0;
}
}
}
cout << s.size() << endl;
}
typedef pair<int,int> pairs;
should be
typedef std::pair<int,int> pairs;
(Or you could move using namespace std; so that it is before your typedef).
Plus typedefing a single pair as the plural pairs is a really really bad idea, that is going to confuse you and anyone else reading your code for the rest of this programs existence. If you want a typedef for a pair of ints, then call it that
typedef std::pair<int,int> pair_of_ints;
To make your last programme works, it was needed to move the declaration of std::vector<int> v;
Moreover, your code has a complexity O(n^3). In practice, it is possible to get a complexity O(n^2), by calculating
iteratively the max and min values.
This code compares your code and the new one. The results are identical. However, I cannot be sure
that your original code does what you intended to do.
#include <iostream>
#include <set>
#include <vector>
#include <utility>
#include <algorithm>
typedef std::pair<int,int> pairs;
//using namespace std;
void print (const std::set<pairs> &s) {
for (auto& p: s) {
std::cout << "(" << p.first << ", " << p.second << ") ";
}
std::cout << "\n";
}
int count_pairs_op (const std::vector<int>& a) {
int max, min;
int n = a.size();
std::set<pairs> s;
for(int i = 0; i < n; i++) {
std::vector<int> v;
for(int j = i; j < n; j++) {
v.push_back(a[j]);
if(v.size() > 1) {
max = *std::max_element(v.begin(), v.end());
min = *std::min_element(v.begin(), v.end());
pairs p1 = std::make_pair(max, min);
s.insert(p1);
}
}
}
print (s);
return s.size();
}
int count_pairs_new (const std::vector<int>& a) {
int max, min;
int n = a.size();
std::set<pairs> s;
for(int i = 0; i < n; i++) {
min = a[i];
max = a[i];
for(int j = i+1; j < n; j++) {
max = std::max (max, a[j]);
min = std::min (min, a[j]);
pairs p1 = std::make_pair(max, min);
s.insert(p1);
}
}
print (s);
return s.size();
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int n;
std::cin >> n;
std::vector<int> a(n);
for(int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::cout << count_pairs_op(a) << std::endl;
std::cout << count_pairs_new(a) << std::endl;
}
It appears that there was a mistake in the understanding of the problem.
For each subarray, we have to consider the maximum and the second maximum.
Moreover, we know that all elements are distinct.
As the size can be up to 10^5, we have to look for a complexity smaller than O(n^2).
In practice, each element can be the second element of two subarrays,
if there exist a greater element before and after it.
We just have to check it.
This can be perfomed by calculating, for each index i, the maximum value before and after it.
Total complexity: O(n)
#include <iostream>
#include <set>
#include <vector>
#include <utility>
#include <algorithm>
int count_pairs_2nd_max (const std::vector<int>& a) {
int n = a.size();
int count = 0;
std::vector<int> max_up(n), max_down(n);
max_up[0] = -1;
for (int i = 1; i < n; ++i) {
max_up[i] = std::max(max_up[i-1], a[i-1]);
}
max_down[n-1] = -1;
for (int i = n-2; i >= 0; --i) {
max_down[i] = std::max(max_down[i+1], a[i+1]);
}
for(int i = 0; i < n; ++i) {
if (max_up[i] > a[i]) count++;
if (max_down[i] > a[i]) count++;
}
return count;
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int n;
std::cin >> n;
std::vector<int> a(n);
for(int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::cout << count_pairs_2nd_max(a) << std::endl;
}

How to compare 2 vectors and create a separate vector based on the comparison

i'm looking at creating an algorithm that will compare 2 vectors (v1,v2), and create a new vector v3 that will hold the values not shared between v1 and v2.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int args[])
{
vector<int> v1 = { 1,2,3,4,5,6,7,8,9 };
vector<int> v2 = { 1,2,6 };
vector<int> v3; //V3 should equal = {3,4,5,7,8,9}.
return 0;
}
The vectors will always be sorted.
If, as in your example, the ranges are sorted then you can use std::set_symmetric_difference. It will return all elements that are not shared between the two ranges. Using you example you would use
std::set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3));
So putting it all together we have
int main()
{
std::vector<int> v1 = { 1,2,3,4,5,6,7,8,9 };
std::vector<int> v2 = { 1,2,6 };
std::vector<int> v3; //V3 should equal = {3,4,5,7,8,9}.
std::set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3));
for (auto e : v3)
std::cout << e << " ";
return 0;
}
Output:
3 4 5 7 8 9
Live example
Sorry to trouble and add new answer here. NathanOliver has given precise answer.
But for fun if I had to write my own function to implement this, I tried it on arrays instead of vector, (for changing code for vector will be trivial task).
Adding my code snippet here.
#include<iostream>
using namespace std;
int arr1[]={2,3,6,10};
int arr2[]={3,5,7,9,10};
int result[10];
int result_size=0;
void getUncommonValues(int *arr1, int size1, int *arr2, int size2){
if ( (size1 == 0) && (size2 == 0) )
return;
if( size1 == 0){
result_size=size2;
for (int i=0; i < size2; i++)
result[i] = arr2[i];
}
if (size2 == 0){
result_size=size1;
for (int i=0; i < size1; i++)
result[i] = arr1[i];
}
int i1=0, i2=0;
while (size1 > i1){
if ( arr1[i1] < arr2[i2]){
result[result_size++] = arr1[i1++];
} else{
if ( arr2[i2] < arr1[i1] )
result[result_size++] = arr2[i2++];
else{
i1++; i2++;
}
}
if ( i2 == size2 ){
for ( ; i1 < size1; i1++)
result[result_size++] = arr1[i1];
}
}
for ( ; i2 < size2 ; i2++){
result[result_size++] = arr2[i2];
}
}
int main(){
getUncommonValues(arr1,sizeof(arr1)/sizeof(int), arr2,sizeof(arr2)/sizeof(int));
for (int i =0; i<result_size; i++)
cout << result[i] <<" ,";
cout << endl;
return 0;
}
Note : here the result is stored in global array and has fixed size.
This can be resolved in vector directly.

Algorithm to compute mode

I'm trying to devise an algorithm in the form of a function that accepts two parameters, an array and the size of the array. I want it to return the mode of the array and if there are multiple modes, return their average. My strategy was to take the array and first sort it. Then count all the occurrences of a number. while that number is occurring, add one to counter and store that count in an array m. So m is holding all the counts and another array q is holding the last value we were comparing.
For example: is my list is {1, 1, 1, 1, 2, 2, 2}
then i would have m[0] = 4 q[0] = 1
and then m[1] = 3 and q[1] = 2.
so the mode is q[0] = 1;
unfortunately i have had no success thus far. hoping someone could help.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, k = 0, counter = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
for(int j = 0; j < n; j++){
while(y[i] == y[j]) {
counter++;
i++;
}
}
m[k] = counter;
q[k] = y[i];
i--; //i should be 1 less since it is referring to an array subscript
k++;
counter = 0;
}
}
Even though you have some good answers already, I decided to post another. I'm not sure it really adds a lot that's new, but I'm not at all sure it doesn't either. If nothing else, I'm pretty sure it uses more standard headers than any of the other answers. :-)
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <iostream>
#include <utility>
#include <functional>
#include <numeric>
int main() {
std::vector<int> inputs{ 1, 1, 1, 1, 2, 2, 2 };
std::unordered_map<int, size_t> counts;
for (int i : inputs)
++counts[i];
std::multimap<size_t, int, std::greater<size_t> > inv;
for (auto p : counts)
inv.insert(std::make_pair(p.second, p.first));
auto e = inv.upper_bound(inv.begin()->first);
double sum = std::accumulate(inv.begin(),
e,
0.0,
[](double a, std::pair<size_t, int> const &b) {return a + b.second; });
std::cout << sum / std::distance(inv.begin(), e);
}
Compared to #Dietmar's answer, this should be faster if you have a lot of repetition in the numbers, but his will probably be faster if the numbers are mostly unique.
Based on the comment, it seems you need to find the values which occur most often and if there are multiple values occurring the same amount of times, you need to produce the average of these. It seems, this can easily be done by std::sort() following by a traversal finding where values change and keeping a few running counts:
template <int Size>
double mode(int const (&x)[Size]) {
std::vector<int> tmp(x, x + Size);
std::sort(tmp.begin(), tmp.end());
int size(0); // size of the largest set so far
int count(0); // number of largest sets
double sum(0); // sum of largest sets
for (auto it(tmp.begin()); it != tmp.end(); ) {
auto end(std::upper_bound(it, tmp.end(), *it));
if (size == std::distance(it, end)) {
sum += *it;
++count;
}
else if (size < std::distance(it, end)) {
size = std::distance(it, end);
sum = *it;
count = 1;
}
it = end;
}
return sum / count;
}
If you simply wish to count the number of occurences then I suggest you use a std::map or std::unordered_map.
If you're mapping a counter to each distinct value then it's an easy task to count occurences using std::map as each key can only be inserted once. To list the distinct numbers in your list simply iterate over the map.
Here's an example of how you could do it:
#include <cstddef>
#include <map>
#include <algorithm>
#include <iostream>
std::map<int, int> getOccurences(const int arr[], const std::size_t len) {
std::map<int, int> m;
for (std::size_t i = 0; i != len; ++i) {
m[arr[i]]++;
}
return m;
}
int main() {
int list[7]{1, 1, 1, 1, 2, 2, 2};
auto occurences = getOccurences(list, 7);
for (auto e : occurences) {
std::cout << "Number " << e.first << " occurs ";
std::cout << e.second << " times" << std::endl;
}
auto average = std::accumulate(std::begin(list), std::end(list), 0.0) / 7;
std::cout << "Average is " << average << std::endl;
}
Output:
Number 1 occurs 4 times
Number 2 occurs 3 times
Average is 1.42857
Here's a working version of your code. m stores the values in the array and q stores their counts. At the end it runs through all the values to get the maximal count, the sum of the modes, and the number of distinct modes.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, j = 0, k = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
j = i;
while (y[j] == y[i]) {
j++;
}
m[k] = y[i];
q[k] = j - i;
k++;
i = j;
}
int max = 0;
int modes_count = 0;
int modes_sum = 0;
for (int i=0; i < k; i++) {
if (q[i] > max) {
max = q[i];
modes_count = 1;
modes_sum = m[i];
} else if (q[i] == max) {
modes_count += 1;
modes_sum += m[i];
}
}
return modes_sum / modes_count;
}

Counting Sort infinite loop

I am writing a counting sort function and when I run it, a window pops up saying "filename.exe has stopped working". After debugging it looks like it is getting stuck in the second for loop. What really confuses me, is if I set maxInt to any number greater than 130000 it works, but if its 130000 or lower than I get that error message. The file I'm using to sort only has about 20 numbers.
#include <iterator>
#include <algorithm>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
std::string file = "";
std::vector<int> numbers;
void CountingSort(vector<int> &numbers);
int main()
{
std::cout << "Which file would you like to sort?\n";
std::cin >> file;
std::ifstream in(file.c_str());
// Read all the ints from in:
std::copy(std::istream_iterator<int>(in), std::istream_iterator<int>(),
std::back_inserter(numbers));
CountingSort(numbers);
// Print the vector with tab separators:
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, "\t"));
std::cout << std::endl;
return 0;
}
struct CalcMaxInt
{
int maxInt;
CalcMaxInt () : maxInt(0) {}
void operator () (int i) { if (i > maxInt) maxInt = i; }
};
void CountingSort(vector<int>& numbers)
{
CalcMaxInt cmi = std::for_each(numbers.begin(), numbers.end(), CalcMaxInt());
//int maxInt = cmi.maxInt + 1;
int maxInt = 130001;
vector <int> temp1(maxInt);
vector <int> temp2(maxInt);
for (int i = 0; i < numbers.size(); i++)
{
temp2[numbers[i]] = temp2[numbers[i]] + 1;
}
for (int i = 1; i <= maxInt; i++)
{
temp2[i] = temp2[i] + temp2[i - 1];
}
for (int i = numbers.size() - 1; i >= 0; i--)
{
temp1[temp2[numbers[i]] - 1] = numbers[i];
temp2[numbers[i]] = temp2[numbers[i]] -1;
}
for (int i =0;i<numbers.size();i++)
{
numbers[i]=temp1[i];
}
return;
}
You are trying to access an element out of proper range.
temp2 has range [0...maxInt-1] but the following code uses temp2[maxInt] which is out of range.
for (int i = 1; i <= maxInt; i++)
{
temp2[i] = temp2[i] + temp2[i - 1];
}
You'll have to fix temp2 to have maxInt+1 elements or i < maxInt to not to see the error.
Isn't the whole point of you doing this:
CalcMaxInt cmi = std::for_each(numbers.begin(), numbers.end(), CalcMaxInt());
To get the max element?
I'd change your code to the following.
void CountingSort(vector<int>& numbers)
{
CalcMaxInt cmi;
std::for_each(numbers.begin(), numbers.end(), cmi);
int maxInt = cmi.maxInt;
vector <int> temp1(maxInt);
vector <int> temp2(maxInt);
// then the rest the same starting with the for loops
// but with the fix that #kcm1700 mentioned to the for loop
}
Shouldn't temp1 be dimensioned numbers.size()+1?