C++ Segmentation fault with same array index - c++

I have the following piece of code:
bool *pho=new bool[n];
memset(pho, 0, sizeof(bool) * n);
for (int i = 0; i < m; i++) {
int d=2;
cout << "i=" << i << ", d="<<d<< endl;
pho[d] = true;
}
Running with input n=8 results in the following output:
i=0, d=2
i=1, d=2
[Segfault]
I don't understand why this is happening! Setting the same location in the array results in a segfault for some reason. I have run the program several times and it always produces the same output.
Stepping through the code with a debugger, I can see that the value of d (the index) is 2 when the array gets accessed.
I have tried using global arrays and also static global arrays, both of which result in the same error.
Is there something wrong with my IDE and compiler? I am using MinGW with Eclipse CDT, running with std/c++11 option enabled.
Here is the whole source file, in case any other part of the program is causing problems:
#include <iostream>
#include <queue>
#include <vector>
#include <unordered_set>
#include <utility>
#include <algorithm>
#include <cstring>
using namespace std;
vector<unordered_set<int>> adj;
static bool *visited;
pair<int, int> dfs(int node) {
if (visited[node])
return make_pair(0, node);
pair<int, int> best = make_pair(0, node);
for (int neigh : adj[node]) {
pair<int, int> alt = dfs(node);
alt.second++;
best = max(best, alt);
}
return best;
}
int main(int argc, char** argv) {
int n, m, def;
cin >> n ;
cin >> m;
bool *pho=new bool[n];
memset(pho, 0, sizeof(bool) * n);
int *degrees=new int[n];
memset(degrees, 0, sizeof(int) * n);
cout << "n="<<n<<", m="<<m<<endl;
for (int i = 0; i < m; i++) {
int d=2;
cout << "i=" << i << ", d="<<d<< endl;
pho[d] = true;
}
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
adj[a].insert(b);
adj[b].insert(a);
degrees[a]++;
degrees[b]++;
}
queue<int> next;
for (int i = 0; i < n; i++) {
if (degrees[i] == 0) {
next.push(i);
}
}
while (!next.empty()) {
int node = next.front();
next.pop();
if (pho[node])
continue;
for (int neigh : adj[node]) {
adj[node].erase(neigh);
adj[neigh].erase(node);
degrees[node]--;
degrees[neigh]--;
if (degrees[neigh] == 1)
next.push(neigh);
}
}
visited=new bool[n];
memset(visited, 0, sizeof(bool) * n);
pair<int, int> pivot = dfs(def);
memset(visited, 0, sizeof(bool) * n);
pair<int, int> end = dfs(pivot.second);
int dist = end.first; //number of edges she only has to walk once
int tree = n - 1; //number of edges in tree
int otherdist = tree - dist; //number of edges she has to walk twice
int total = dist + otherdist * 2;
cout << total << endl;
return 0;
}

These lines are wrong :
adj[a].insert(b);
adj[b].insert(a);
You need to create unordered_map instance with a and b as keys, then respectively insert b and a as value. You don't need to have a vector of sets if you need key-value pairs.

Related

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;
}

Filling an 1D array in C++

I have an integer array:
int listint[10] = {1,2,2,2,4,4,5,5,7,7,};
What I want to do is to create another array in terms of the multiplicity. So I define another array by:
int multi[7]={0};
the first index of the multi array multi[0] will tell us the number of multiplicity of the array listint that has zero. We can easily see that, there is no zero in the array listint, therefore the first member would be 0. Second would be 1 spice there are only 1 member in the array. Similarly multi[2] position is the multiplicity of 2 in the listint, which would be 3, since there are three 2 in the listint.
I want to use an for loop to do this thing.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count;
int j;
int listint[10] = { 1,2,2,2,4,4,5,5,7,7, };
int multi[7] = { 0 };
for (int i = 0; i < 9; i++)
{
if (i == listint[i])
count++;
j = count;
multi[j] = 1;
}
cout << "multi hit \n" << multi[1] << endl;
return 0;
}
After running this code, I thought that I would want the multiplicity of the each element of the array of listint. So i tried to work with 2D array.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count;
int i, j;
int listint[10] = { 1,2,2,2,4,4,5,5,7,7, };
int multi[7][10] = { 0 };
for (int i = 0; i < 9; i++)
{
if (i == listint[i])
count++;
j = count;
for (j = 0; j < count; j++) {
multi[j][i] = 1;
}
}
cout << "multi hit \n" << multi[4][i] << endl;
return 0;
}
The first code block is something that I wanted to print out the multiplicity. But later I found that, I want in a array that multiplicity of each elements. SO isn't the 2D array would be good idea?
I was not successful running the code using 2D array.
Another question. When I assign j = count, I mean that that's the multiplicity. so if the value of count is 2; I would think that is a multiplicity of two of any element in the array listint.
A 2d array is unnecessary if you're just trying to get the count of each element in a list.
#include <iostream>
int main() {
int listint[10] = { 1,2,2,2,4,4,5,5,7,7, };
int multi[8] = { 0 };
for (int i : listint)
++multi[i];
for (int i = 0; i < 8; ++i)
std::cout << i << ": " << multi[i] << '\n';
return 0;
}
There's also a simpler and better way of doing so using the standard collection std::map. Notably, this doesn't require you to know what the largest element in the array is beforehand:
#include <map>
#include <iostream>
int main() {
int listint[10] = {1,2,2,2,4,4,5,5,7,7,};
std::map<int, int> multi;
for (int i : listint)
multi[i]++;
for (auto [k,v] : multi)
std::cout << k << ": " << v << '\n';
}
Try this incase maps won't work for you since you're a beginner, simple:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count;
int j;
int listint[10] = {1,2,2,2,4,4,5,5,7,7};
int multi[8]={0};
for(int i=0; i<10; i++)
{
multi[listint[i]]++; // using listint arrays elements as index of multi to increase count.
}
for( int i=1; i<8; i++)
{
cout << "multi hit of "<<i<<" : "<< multi[i]<<endl;
}
return 0;
}
OR if numbers could get large and are unknown but sorted
#include <iostream>:
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count = 0;
int index = 0; // used to fill elements in below arrays
int Numbers[10] = {0}; // storing unique numbers like 1,2,4,5,7...
int Count[10] = {0}; // storing their counts like 1,3,2,2,2...
int listint[10] = {1, 2, 2, 2, 4, 4, 5, 5, 7, 7};
for(int i = 0; i < sizeof(listint) / sizeof(listint[0]); i++)
{
count++;
if (listint[i] != listint[i+1]) {
Numbers[index] = listint[i];
Count[index] = count;
count=0;
index++;
}
}
for(int i=0; i<index; i++)
{
cout << "multi hit of "<<Numbers[i]<<" is " << Count[i]<<endl;
}
return 0;
}

How to display minimum spannign tree matrix

#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include<iomanip>
using namespace std;
typedef pair<int, int> intPair;// rename intPair
typedef vector<double> doubleVector; //rename doubleVetcor
typedef vector<intPair> intPairVector; // rename intPairVector
// Union-Find Disjoint Sets Library written in OOP manner, using both path compression and union by rank heuristics
class UnionFind { // OOP style
private:
doubleVector p, rank, setSize; // remember: vi is vector<double>
int numSets;
public:
UnionFind(int N) {
setSize.assign(N, 1);
numSets = N;
rank.assign(N, 0);
p.assign(N, 0);
for (int i = 0; i < N; i++)
p[i] = i;
}
int findSet(int i) {
return (p[i] == i) ? i : (p[i] = findSet(p[i]));
}
bool isSameSet(int i, int j) {
return findSet(i) == findSet(j);
}
void unionSet(int i, int j) {
if (!isSameSet(i, j)) {
numSets--;
int x = findSet(i), y = findSet(j);
// rank is used to keep the tree short
if (rank[x] > rank[y]) {
p[y] = x;
setSize[x] += setSize[y];
}
else{
p[x] = y;
setSize[y] += setSize[x];
if (rank[x] == rank[y])
rank[y]++;
}
}
}
int numDisjointSets() {
return numSets;
}
int sizeOfSet(int i) {
return setSize[findSet(i)];
}
};
vector<intPairVector> AdjList;
int main() {
int num_verts=0;
cin >> num_verts;
//Pre-allocate a vector of num_verts rows, each of which is a vector
//of num_verts copies of 0.0
vector<vector<double>> matrix(num_verts, vector<double>(num_verts,0.0));
//Requires c++11 or higher
for(int row = 0; row<num_verts;++row) {
for(int col = 0; col<num_verts; ++col){
cin >> matrix[row][col];
}
}
//print out the matrix we just read
for(int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
cout << setprecision(2) << fixed << matrix[row][col] << "\t";
}
cout << "\n";
}
// Kruskal's algorithm merged
AdjList.assign(num_verts, intPairVector());
vector< pair<double, intPair> > EdgeList; // (weight, two vertices) of the edge
for (int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
EdgeList.push_back(make_pair(matrix[row][col], intPair(row,col)));
AdjList[row].push_back(intPair(row,matrix[row][col]));
AdjList[col].push_back(intPair(col,matrix[row][col]));
}
}
sort(EdgeList.begin(), EdgeList.end()); // sort by edge weight O(E log E)
// note: pair object has built-in comparison function
double mst_cost = 0.0;
UnionFind UF(num_verts); // all V are disjoint sets initially
for (int i = 0; i < num_verts*num_verts; i++) { // for each edge, O(E)
pair<double,intPair> front = EdgeList[i];
if (!UF.isSameSet(front.second.first, front.second.second)) { // check
mst_cost += front.first; // add the weight of e to MST
UF.unionSet(front.second.first, front.second.second); // link them
}
} // note: the runtime cost of UFDS is very light
//display the weight of the MST
cout << setprecision(2) << fixed << mst_cost << endl;
return 0;
}
I am trying to display the minimum spanning tree from this code, I cannot figure out how to get this code to display the modified matrix. The code is working correctly, by that I mean it is compiling and calculating the correct weight for the graph. However, I am unsure how to display the minimum spanning tree from using Kruskals algorithm. Thanks for any help
Whenever you add the weight of an edge to the weight of the MST, you should also add that edge to a list to keep track of the MST edges.

Error implementing selection sort in C++

I've written this code to sort an array using selection sort, but it doesn't sort the array correctly.
#include <cstdlib>
#include <iostream>
using namespace std;
void selectionsort(int *b, int size)
{
int i, k, menor, posmenor;
for (i = 0; i < size - 1; i++)
{
posmenor = i;
menor = b[i];
for (k = i + 1; k < size; k++)
{
if (b[k] < menor)
{
menor = b[k];
posmenor = k;
}
}
b[posmenor] = b[i];
b[i] = menor;
}
}
int main()
{
typedef int myarray[size];
myarray b;
for (int i = 1; i <= size; i++)
{
cout << "Ingrese numero " << i << ": ";
cin >> b[i];
}
selectionsort(b, size);
for (int l = 1; l <= size; l++)
{
cout << b[l] << endl;
}
system("Pause");
return 0;
}
I can't find the error. I'm new to C++.
Thanks for help.
The selectionSort() function is fine. Array init and output is not. See below.
int main()
{
int size = 10; // for example
typedef int myarray[size];
myarray b;
for (int i=0;i<size;i++)
//------------^^--^
{
cout<<"Ingrese numero "<<i<<": ";
cin>>b[i];
}
selectionsort(b,size);
for (int i=0;i<size;i++)
//------------^^--^
{
cout<<b[l]<<endl;
}
system("Pause");
return 0;
}
In C and C++, an array with n elements starts with the 0 index, and ends with the n-1 index. For your example, the starting index is 0 and ending index is 9. When you iterate like you do in your posted code, you check if the index variable is less than (or not equal to) the size of the array, i.e. size. Thus, on the last step of your iteration, you access b[size], accessing the location in memory next to the last element in the array, which is not guaranteed to contain anything meaningful (being uninitialized), hence the random numbers in your output.
You provided some sample input in the comments to your question.
I compiled and executed the following, which I believe accurately reproduces your shown code, and your sample input:
#include <iostream>
void selectionsort(int* b, int size)
{
int i, k, menor, posmenor;
for(i=0;i<size-1;i++)
{
posmenor=i;
menor=b[i];
for(k=i+1;k<size;k++)
{
if(b[k]<menor)
{
menor=b[k];
posmenor=k;
}
}
b[posmenor]=b[i];
b[i]=menor;
}
}
int main(int argc, char **argv)
{
int a[10] = {-3, 100, 200, 2, 3, 4, -4, -5, 6, 0};
selectionsort(a, 10);
for (auto v:a)
{
std::cout << v << ' ';
}
std::cout << std::endl;
}
The resulting output was as follows:
-5 -4 -3 0 2 3 4 6 100 200
These results look correct. I see nothing wrong with your code, and by using the sample input you posted, this confirms that.

Can't understand why my program throws error

My code is in
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
#include <vector>
#include <cmath>
using namespace std;
struct State {
int v;
const State *rest;
void dump() const {
if(rest) {
cout << ' ' << v;
rest->dump();
} else {
cout << endl;
}
}
State() : v(0), rest(0) {}
State(int _v, const State &_rest) : v(_v), rest(&_rest) {}
};
void ss(int *ip, int *end, int target, const State &state) {
if(target < 0) return; // assuming we don't allow any negatives
if(ip==end && target==0) {
state.dump();
return;
}
if(ip==end)
return;
{ // without the first one
ss(ip+1, end, target, state);
}
{ // with the first one
int first = *ip;
ss(ip+1, end, target-first, State(first, state));
}
}
vector<int> get_primes(int N) {
int size = floor(0.5 * (N - 3)) + 1;
vector<int> primes;
primes.push_back(2);
vector<bool> is_prime(size, true);
for(long i = 0; i < size; ++i) {
if(is_prime[i]) {
int p = (i << 1) + 3;
primes.push_back(p);
// sieving from p^2, whose index is 2i^2 + 6i + 3
for (long j = ((i * i) << 1) + 6 * i + 3; j < size; j += p) {
is_prime[j] = false;
}
}
}
}
int main() {
int N;
cin >> N;
vector<int> primes = get_primes(N);
int a[primes.size()];
for (int i = 0; i < primes.size(); ++i) {
a[i] = primes[i];
}
int * start = &a[0];
int * end = start + sizeof(a) / sizeof(a[0]);
ss(start, end, N, State());
}
It takes one input N (int), and gets the vector of all prime numbers smaller than N.
Then, it finds the number of unique sets from the vector that adds up to N.
The get_primes(N) works, but the other one doesn't.
I borrowed the other code from
How to find all matching numbers, that sums to 'N' in a given array
Please help me.. I just want the number of unique sets.
You've forgotten to return primes; at the end of your get_primes() function.
I'm guessing the problem is:
vector<int> get_primes(int N) {
// ...
return primes; // missing this line
}
As-is, you're just writing some junk here:
vector<int> primes = get_primes(N);
it's undefined behavior - which in this case manifests itself as crashing.