Program containing threading in cpp is not executed completely - c++

Code given below is not executed completely;
I have looked for everything on web but I don't know why it is working for starting numbers from nums (i.e. 1000 and sometimes 5000) and after that it starts execution but in between program terminates itself and stopes working.
#include <bits/stdc++.h>
// #include <iostream>
// #include <chrono>
// #include <vector>
#define UPPER_LIMIT 10
using namespace std;
using namespace std::chrono;
bool inTimeLimit = true;
bool isFinished = false;
bool isRunning = true;
class Timer {
public:
time_point<high_resolution_clock> start, end;
Timer() {
start = high_resolution_clock::now();
}
~Timer() {
end = high_resolution_clock::now();
auto durationTime = durationCounter();
cout << "\n\nTaken time Duration " << (unsigned long long)durationTime << " us; " << (unsigned long long)durationTime * 0.001 << "ms.";
}
float durationCounter() {
auto currTime = high_resolution_clock::now();
auto durationTime = duration_cast<microseconds>(currTime - start);
return durationTime.count();
}
};
void printVector(vector <int> v) {
cout << endl;
for (int x : v) {
cout << setw(3) << x << " ";
}
}
void printVectorToFile(ofstream &fout , vector <int> v, string msg) {
fout << "\n\n===================\n\n";
fout << msg << endl;
fout << endl;
for (int x : v) {
fout << setw(5) << x << " ";
}
fout << endl;
}
void swap (int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
vector <int> randomArrayGenerator(int n) {
vector<int> v(n);
for (int i = 0; i < n; ++i)
v[i] = i + 1;
srand(time(0));
for (int i = 0; i < n; ++i)
{
int pos = rand() % n;
swap(&v[i], &v[pos]);
}
return v;
}
string sortingChecker(vector<int> v) {
for (int i = 0; i < (int)v.size() - 1; ++i)
{
if (v[i] > v[i + 1]) return "false";
}
return "true";
}
bool sortChecker(vector<int> v) {
for (int i = 0; i < (int)v.size() - 1; ++i)
{
if (v[i] > v[i + 1]) return false;
}
return true;
}
// Merge function
void merge(vector <int> &v, int begin, int middle, int end) {
vector <int> left, right;
for (int i = begin; i < middle + 1; ++i)
{
left.push_back(v[i]);
}
for (int i = middle + 1; i <= end; ++i)
{
right.push_back(v[i]);
}
int p1 = 0, p2 = 0, n1 = left.size(), n2 = right.size(), p = begin;
while ((p1 < n1 ) || (p2 < n2)) {
if ((p1 != n1 ) && ((p2 == n2) || left[p1] < right[p2]))
v[p++] = left[p1++];
else
v[p++] = right[p2++];
}
}
void mergeSortByIteration(vector <int> &v, bool &isTimeDelayed) {
int low = 0, high = v.size();
cout << "Thread ID: " << this_thread::get_id() << endl;
// n :for taking individual block of vector containing number of elements n=[1,2,4,8,..]
for (int n = 1; n < high; n *= 2) {
if (isTimeDelayed) return;
// taking block according to n and then sorting them by merge function
// n=1 => i=0,2,4,8,16
// n=2 => i=0,4,8
for (int i = 0; i < high; i += 2 * n) {
if (isTimeDelayed) return;
int begin = i;
int mid = i + n - 1;
int end = min(i + 2 * n - 1 , high - 1);
merge(v, begin, mid, end);
}
}
}
// Merge by recurision
void mergeSortByRecursion (vector <int> &v, int begin, int end, bool &isTimeDelayed) {
if (end <= begin || isTimeDelayed) return;
int middle = begin + (end - begin) / 2;
mergeSortByRecursion(v, begin, middle, isTimeDelayed);
mergeSortByRecursion(v, middle + 1, end, isTimeDelayed);
merge(v, begin, middle, end);
}
int main() {
int nums[] = {1000, 5000, 10000, 50000, 100000};
// int nums[] = {50000};
ofstream vectorOutput ;
vectorOutput.open("outputTexts\\prac1_resultedArrays.txt", ios::trunc);;
for (int n : nums)
// ``````` Merge by Iteration ````````
{
vector<int> num, arr = randomArrayGenerator(n);
cout << "\n=======";
cout << "\n\nMerge by Iteration:" << endl;
num = arr;
cout << "Array size: " << num.size() << endl;
bool isTimeOut = false, isSorted = false;
Timer timer;
std::thread worker(mergeSortByIteration, ref(num), ref(isTimeOut));
// mergeSortByIteration(num, isTimeOut);
// std::thread worker(mergeSortByRecursion, ref(num), 0, n - 1, ref(isTimeOut));
while ( ( ( timer.durationCounter() / 1000000 ) < 5) && (!isSorted ) ) {
// this_thread::sleep_for(seconds(1));
// cout << timer.durationCounter() << " ";
isSorted = sortChecker(num);
}
if ( ( ( ( timer.durationCounter() / 1000000 ) > 5) && (!isSorted ) ) )
{
isTimeOut = true;
cout << endl << "!!!!!Execution Terminated ---- Time Limit reached!!!!!!" << endl;
}
if (worker.joinable())
worker.join();
printVector(num);
cout << "\nCheck result for sorted Vector:" << (isSorted ? "true" : "false") << endl;
// printVectorToFile(vectorOutput, num, "Merge By Iteration for size:" + to_string(n) );
}
cout << "\n\ndone" << endl;
return 0;
}
can anyone help me out here?
If issue is not clear fill free to ask.

Related

How to avoid loop removal with -O3 and the performance impact of asm("") when benchmarking a C++ code block?

I'm trying to microbenchmark the following C++ code, compiled with the -O3 g++ compiler option for maximum performance:
long long x = 0;
int iterations = 1000000;
int load = 1000;
for(int i = 0; i < iterations; i++) {
long start = get_nano_ts(&ts);
for(int j = 0; j < load; j++) {
long p = (i % 8) * (i % 16);
if (i % 2 == 0) {
x += p;
} else {
x -= p;
}
asm(""); // so that the loop is not removed by -O3
}
long end = get_nano_ts(&ts);
int res = end - start - nanoTimeCost;
if (res <= 0) res = 1;
// (...) removed for clarity
}
cout << "Value computed: " << x << endl;
As you can see I'm using the asm("") instruction to prevent the compiler from turning my loop calculation into something else. How do I know it is turning my loop calculation into something else? That's because without the asm("") line, the value is calculated immediately and the program exits immediately, no matter how large I make the load variable.
So my question is: How can I use the -O3 compiler option and still prevent it from turning my loop into something else?
From this SO question, I got that I have to use asm("") for that. But then my question becomes: Wouldn't asm("") mess with my timing (add overhead) and/or prevent the compiler from doing other valid/good optimizations like inlining?
Another solution for me would be to come up with a for/loop code that cannot be translated to a straight mathematical formula by the compiler, in other words, some kind of mathematical computation that really requires a loop to be executed. Any suggestions?
Below the full C++ code I'm using:
#include <iostream>
#include <string>
#include <random>
#include <cmath>
#include <algorithm>
#include <limits>
#include <sys/time.h>
#include <map>
#include <sched.h>
#include <sstream>
#include <iomanip>
using namespace std;
// TO COMPILE: g++ TestJitter.cpp -o TestJitter -std=c++11 -O3
// TO EXECUTE: ./TestJitter 10000000 1000000 1000 1
static const bool MORE_PERCS = true;
static const bool INCLUDE_WORST_PERCS = true;
static const bool INCLUDE_TOTALS = true;
static const bool INCLUDE_RATIOS = false;
static const bool INCLUDE_STDEV = true;
static const bool EXCLUDE_NANO_TS_COST = true;
long get_nano_ts(timespec* ts) {
clock_gettime(CLOCK_MONOTONIC, ts);
return ts->tv_sec * 1000000000 + ts->tv_nsec;
}
static const long NANO_COST_ITERATIONS = 10000000;
static long calc_nano_ts_cost() {
struct timespec ts;
long start = get_nano_ts(&ts);
long finish = start;
for (long i = 0; i < NANO_COST_ITERATIONS; i++) {
finish = get_nano_ts(&ts);
}
finish = get_nano_ts(&ts);
return (finish - start) / NANO_COST_ITERATIONS;
}
struct mi {
long value;
};
void add_perc(stringstream& ss, int size, double perc, map<int, mi*>* map) {
if (map->empty()) return;
int max = -1;
int minBottom = -1;
long x = round(perc * size);
long i = 0;
long iBottom = 0;
long sum = 0;
long sumBottom = 0;
bool trueForTopFalseForBottom = true;
bool flag = false;
const int arraySize = 1024 * 1024 * 10;
int* tempData = new int[arraySize];
double stdevTop = -1;
for(auto iter = map->begin(); iter != map->end(); iter++) {
if (flag) break;
int time = iter->first;
long count = (iter->second)->value;
for(int a = 0; a < count; a++) {
if (trueForTopFalseForBottom) {
tempData[i] = time;
i++;
sum += time;
if (i == x) {
max = time;
if (INCLUDE_STDEV) {
double avg = (double) sum / (double) i;
double temp = 0;
for(int b = 0; b < i; b++) {
int t = tempData[b];
temp += (avg - t) * (avg - t);
}
stdevTop = sqrt(((double) temp / (double) i));
}
if (INCLUDE_WORST_PERCS) {
trueForTopFalseForBottom = false;
} else {
flag = true;
break;
}
}
} else {
tempData[iBottom] = time;
iBottom++;
sumBottom += time;
if (minBottom == -1) {
minBottom = time;
}
}
}
}
ss << " | " << fixed << setprecision(5) << (perc * 100) << "%";
if (INCLUDE_TOTALS) ss << " (" << i << ")";
ss << " = [avg: " << (sum / i);
if (INCLUDE_STDEV) ss << ", stdev: " << fixed << setprecision(2) << stdevTop;
ss << ", max: " << max << "]";
if (INCLUDE_WORST_PERCS) {
ss << " - " << fixed << setprecision(5) << ((1 - perc) * 100) << "%";
if (INCLUDE_TOTALS) ss << " (" << (iBottom > 0 ? iBottom : 0) << ")";
ss << " = [avg: " << (iBottom > 0 ? (sumBottom / iBottom) : -1);
if (INCLUDE_STDEV) {
ss << ", stdev: ";
if (iBottom <= 0) {
ss << "?";
} else {
double avgBottom = (sumBottom / iBottom);
double temp = 0;
for(int b = 0; b < iBottom; b++) {
long t = tempData[b];
temp += (avgBottom - t) * (avgBottom - t);
}
double stdevBottom = sqrt((double) temp / (double) iBottom);
ss << fixed << setprecision(2) << stdevBottom;
}
}
ss << ", min: " << (minBottom != -1 ? minBottom : -1) << "]";
if (INCLUDE_RATIOS) {
ss << " R: ";
ss << fixed << setprecision(2) << (iBottom > 0 ? (((sumBottom / iBottom) / (double) (sum / i)) - 1) * 100 : -1);
ss << "%";
}
}
delete[] tempData;
}
int main(int argc, char* argv[]) {
int iterations = stoi(argv[1]);
int warmup = stoi(argv[2]);
int load = stoi(argv[3]);
int proc = stoi(argv[4]);
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(proc, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
long nanoTimeCost = EXCLUDE_NANO_TS_COST ? calc_nano_ts_cost() : 0;
struct timespec ts;
long long x = 0;
long long totalTime = 0;
int minTime = numeric_limits<int>::max();
int maxTime = numeric_limits<int>::min();
map<int, mi*>* results = new map<int, mi*>();
for(int i = 0; i < iterations; i++) {
long start = get_nano_ts(&ts);
for(int j = 0; j < load; j++) {
long p = (i % 8) * (i % 16);
if (i % 2 == 0) {
x += p;
} else {
x -= p;
}
asm(""); // so that the loop is not removed by -O3
}
long end = get_nano_ts(&ts);
int res = end - start - nanoTimeCost;
if (res <= 0) res = 1;
if (i >= warmup) {
totalTime += res;
minTime = min(minTime, res);
maxTime = max(maxTime, res);
auto iter = results->find(res);
if (iter != results->end()) {
(iter->second)->value = (iter->second)->value + 1;
} else {
mi* elem = new mi();
elem->value = 1;
(*results)[res] = elem;
}
}
}
int count = iterations - warmup;
double avg = totalTime / count;
cout << "Value computed: " << x << endl;
cout << "Nano timestamp cost: " << nanoTimeCost << endl;
stringstream ss;
ss << "Iterations: " << count << " | Avg Time: " << avg;
if (INCLUDE_STDEV) {
long temp = 0;
long x = 0;
for(auto iter = results->begin(); iter != results->end(); iter++) {
int time = iter->first;
long count = (iter->second)->value;
for(int a = 0; a < count; a++) {
temp += (avg - time) * (avg - time);
x++;
}
}
double stdev = sqrt( temp / x );
ss << " | Stdev: " << fixed << setprecision(2) << stdev;
}
if (count > 0) {
ss << " | Min Time: " << minTime << " | Max Time: " << maxTime;
}
add_perc(ss, count, 0.75, results);
add_perc(ss, count, 0.90, results);
add_perc(ss, count, 0.99, results);
add_perc(ss, count, 0.999, results);
add_perc(ss, count, 0.9999, results);
add_perc(ss, count, 0.99999, results);
if (MORE_PERCS) {
add_perc(ss, count, 0.999999, results);
add_perc(ss, count, 0.9999999, results);
}
cout << ss.str() << endl << endl;
delete results;
return 0;
}

Find duplicate consecutive numbers in a randomly generated array

I want to find duplicate numbers in a row (2 in a row, 3 in a row, ...) in a randomly generated array. I can't make it further than this:
#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <ctime>
#include <array>
#include <algorithm>
using namespace std;
int main()
{
srand(time(NULL));
const int velikostPolja = 100;
int a[velikostPolja];
int y = 0;
int x = 0;
for (int i = 0; i < velikostPolja; i++)
{
a[i] = rand() % 10;
cout << a[i];
}
cout << endl;
for (int i = 0; i < velikostPolja; i++)
{
if (a[i] == a[i + 1])
x++;
}
cout << endl;
cout << "Two times repated in row: " << x << endl;
system("pause");
return 0;
}
You could do it like this:
int count[velikostPolja] = { 0 };
int c = 0;
for (int i = 1; i < velikostPolja; i++)
{
if (a[i] == a[i - 1])
{
++c;
}
else
{
++count[c];
c = 0;
}
}
for (int i = 1; i < velikostPolja; i++)
{
if (count[i])
{
cout << i + 1 << " times repeated in row: " << count[i] << endl;
}
}
This does not account for any repeats at the end of a, though. I leave that as an exercise for you to do yourself.
You might use:
template <typename IT>
std::size_t count_repetition(IT begin, IT end, std::size_t count)
{
std::size_t res = 0;
auto it = begin;
while (it != end) {
it = std::adjacent_find(it, end);
if (it == end){
return res;
}
const auto it2 = std::find_if(it, end, [it](const auto& e) { return e != *it; });
const auto dist = std::distance(it, it2);
if (count <= dist) {
// how to count 2-repetition for {a, a, a, a}
#if 0
++res; // Count only as 1
#else
res += dist + 1 - count; // count as 3
#endif
}
it = it2;
}
return res;
}
Demo

Difference in runtime C++ using different data types

Ok, so I was doing a tiny project for school and I can't find the answer anywhere to why this small change in code makes it finish in no time when number m gets higher. Look at the variable "k" I change it from int to long.
I'm trying to find the longest sequence in the Collatz sequence between 1 and 1000000
void lengstaRuna() {
cout << "Hæsta tala?:";
int m;
cin >> m;
int lengstaRuna = 0;
int talaLengstuRunu = 0;
int k;
for(int i = 2; i < m; i++) {
int lengd = 1;
k = i;
while(k != 1) {
if(k % 2 == 0) {
k = k/2;
} else {
k = k*3 +1;
}
lengd++;
}
if(lengd > lengstaRuna) {
lengstaRuna = lengd;
talaLengstuRunu = i;
}
}
cout << "Lengsta runa: " << lengstaRuna << endl;
cout << "Tala lengstu runu: " << talaLengstuRunu << endl;
}
void lengstaRuna() {
cout << "Hæsta tala?:";
int m;
cin >> m;
int lengstaRuna = 0;
int talaLengstuRunu = 0;
long k;
for(int i = 2; i < m; i++) {
int lengd = 1;
k = i;
while(k != 1) {
if(k % 2 == 0) {
k = k/2;
} else {
k = k*3 +1;
}
lengd++;
}
if(lengd > lengstaRuna) {
lengstaRuna = lengd;
talaLengstuRunu = i;
}
}
cout << "Lengsta runa: " << lengstaRuna << endl;
cout << "Tala lengstu runu: " << talaLengstuRunu << endl;
}
The question is simple: Why does it run so much faster when input m==1000000?
I see what's happening here. Basically, above certain value for your input, the int is overflowing since you are doing k*3.
I modified your code to check this (see below). Upto input value of around 113000, the max your 'k' has to hold is 1570824735 (close to INT_MAX 2147483647). Anything 114000 or above, 'k' overflows and the code goes into uncharted territory. That problem doesn't happen when you use long of course.
./a.out 113000
j: 1570824735
Lengsta runa: 354
Tala lengstu runu: 106239
#include <iostream>
#include <string>
using namespace std;
void lengstaRuna(int m) {
int lengstaRuna = 0;
int talaLengstuRunu = 0;
int k;
long j = 0;
for(int i = 2; i < m; i++) {
int lengd = 1;
k = i;
while(k != 1) {
if(k % 2 == 0) {
k = k/2;
} else {
if (k*3 > j)
j = k*3;
k = k*3 +1;
}
lengd++;
}
if(lengd > lengstaRuna) {
lengstaRuna = lengd;
talaLengstuRunu = i;
}
}
cout << "j: " << j << endl;
cout << "Lengsta runa: " << lengstaRuna << endl;
cout << "Tala lengstu runu: " << talaLengstuRunu << endl;
}
int main (int ac, char** av) {
std::string::size_type sz;
lengstaRuna(std::stoi(av[1]));
}

C++ : Creating a mathematical set to compute subset checking

I would like to know how to check for subset and proper subset of two arrays. I cannot figure out a logical way to check for the subset of two arrays. Here is what I have so far.
Here is my Code:
Sets.h
#ifndef SETS_H
#define SETS_H
using namespace std;
class Sets{
private:
static const int SIZE = 5;
int arr[SIZE];
public:
Sets();
void addElement(int);
int getElement(int);
int getSize();
bool isSubset(Sets);
bool isProper(Sets);
void printSet();
void printOrderedPairs(Sets);
};
#endif
Sets.cpp
#include "Sets.h"
#include <iostream>
using namespace std;
Sets::Sets(){
for (int i = 0; i < SIZE; i++){
arr[i] = -1;
}
}
int Sets::getSize(){
return SIZE;
}
void Sets::addElement(int l){
for (int i = 0; i < SIZE; i++){
if (arr[i] == -1){
arr[i] = l;
break;
}
}
}
int Sets::getElement(int j){
if (j < SIZE){
return (-1);
}
else{
int temp;
temp = arr[j];
return temp;
}
}
bool Sets::isSubset(Sets b){
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (arr[i] != b.arr[i]){
return false;
}
}
}
return true;
}
bool Sets::isProper(Sets b){
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (arr[i] != b.arr[j]){
return false;
}
}
}
return true;
}
void Sets::printOrderedPairs(Sets b){
cout << "A X B = {";
for (int i = 0; i < SIZE-1; i++){
for (int j = 0; j < SIZE; j++){
cout << "(" << arr[i] << "," << b.arr[j] << ") , ";
}
}
cout << "}";
}
void Sets::printSet(){
cout << "{";
for (int i = 0; i < SIZE; i++){
cout << arr[i] << " ,";
}
cout << "}";
}
TestSets.cpp
#include <iostream>
#include "Sets.h"
using namespace std;
int main(){
Sets a;
Sets b;
a.addElement(1);
a.addElement(3);
a.addElement(5);
a.addElement(7);
a.addElement(9);
b.addElement(1);
b.addElement(3);
b.addElement(5);
b.addElement(7);
b.addElement(9);
cout << "Set A is ";
a.printSet();
cout << endl;
cout << "Set B is ";
b.printSet();
cout << "\n" << endl;
a.printOrderedPairs(b);
cout << "\n" << endl;
if (a.isSubset(b) == true){
cout << "Set B is subset of set A" << endl;
}
else{
cout << "Set B is not a subset of set A" << endl;
}
if (a.isProper(b) == true){
cout << "Set B is proper subset of set A" << endl;
}
else{
cout << "Set B is not a proper subset of set A" << endl;
}
system("PAUSE");
return 0;
}
Any help would be appreciate at this point. Thanks in advance.
A way to check is a set b is a subset of another set a is to loop through each element of b and verify that it is present in a. This is faster if both the sets are sorted (and that's the case of std::set for example).
Your class uses an array of int (and it would be better using a std::vector instead) of fixed size (5, for whatever reason). I think it should be an improvment using some dynamical allocation instead.
So, to check if a set is a subset I'll suggest you something like:
// a.isSubset(b) check if b is a subset of a
bool Sets::isSubset( const Sets &b ) {
for (int i = 0; i < b.size; i++ ) {
bool is_present = false;
for (int j = 0; j < size; j++ ) {
// b is a subset if all of its element are in a
// so check if any element of b is in a
if ( arr[j] == b.arr[i] ) {
is_present = true;
break;
}
}
if ( !is_present ) return false;
}
return true;
}
// a.isProper(b) check if b is a proper subset of a
bool Sets::isProper( const Sets &b) {
int n_equals = 0;
for (int i = 0; i < b.size; i++) {
bool is_present = false;
for (int j = 0; j < size; j++) {
// b is a prpoper subset if all of its element are in a
// but there exists at least one element of a that is not in b
if ( arr[j] == b.arr[i] ) {
is_present = true;
++n_equals;
break;
}
}
if ( !is_present ) return false;
}
return n_equals < size;
}
Your class should be modified accordingly.
EDIT
To gain better performances and to simplify most of the algorithms it's better to use a sorted container. For example, the two function belove may become:
// a.isSubset(b) check if b is a subset of a. Requires that both are sorted
bool Sets::isSubset( const Sets &b ) {
for (int i = 0, j = 0; i < b.size; i++ ) {
// scan a, which is sorted
while ( j < size && arr[j] < b.arr[i] ) ++j;
if ( j == size || arr[j] > b.arr[i] )
// There's at least one element of b which not belongs to a
return false;
// b.arr[i] == arr[j], move on
}
// all the element of b are in a too
return true;
}
// a.isProper(b) check if b is a proper subset of a.
// It requires that both are sorted
bool Sets::isProper( const Sets &b ) {
int n_equals = 0;
for (int i = 0, j = 0; i < b.size; i++ ) {
while ( j < size && arr[j] < b.arr[i] ) ++j;
if ( j == size || arr[j] > b.arr[i] )
// b is a prpoper subset if all of its element are in a
// but there exists at least one element of a that is not in b
return false;
++n_equals;
}
return n_equals < size;
}
To force the sorting you only have to modify the function that adds elements. I added some helper functions too:
#include <iostream>
using namespace std;
class Sets{
private:
int size;
int allocated;
int *arr;
// It's way better using a std::vector:
// vector<int> v;
// or you can cheat and use a std::set
public:
Sets();
~Sets();
void addElement(int);
void delElement(int);
int getLowerPos(int);
int getElement(int);
int getSize();
bool doesContain(int);
bool isSubset(const Sets &);
bool isProper(const Sets &);
void printSet();
void printOrderedPairs(const Sets &);
};
Sets::Sets() : size(0), allocated(0), arr(nullptr) { }
Sets::~Sets() {
delete[] arr;
}
int Sets::getSize(){
return size;
}
// Add an element if it isn't already present, keeping the array sorted
void Sets::addElement( int x ) {
int pos = this->getLowerPos(x);
if ( pos < size && arr[pos] == x ) return;
if ( size == allocated ) {
// it's time to expand the array. If it's empty, start from 8
allocated = allocated > 0 ? allocated * 2 : 8;
int *new_arr = new int[allocated];
for ( int i = 0; i < pos; i++ ) {
new_arr[i] = arr[i];
}
for ( int i = size; i > pos; --i ) {
new_arr[i] = arr[i - 1];
}
delete[] arr;
arr = new_arr;
}
else {
for ( int i = size; i > pos; --i ) {
arr[i] = arr[i - 1];
}
}
arr[pos] = x;
++size;
}
// Remove an element from the set if it is present, keeping the array sorted
void Sets::delElement( int x ) {
int pos = this->getLowerPos(x);
if ( pos == size || arr[pos] != x ) return;
// I move the elements and update size only, without deallocation.
--size;
for ( int i = pos; i < size; ++i ) {
arr[i] = arr[i + 1];
}
}
// I guess you want to return the element j of the set or -1 if it's not present
int Sets::getElement( int j ){
// consider using size_t instead of int for indeces or at least unsigned int
if ( j < 0 || j >= size )
// I assume all the elements are positive integers
return -1;
else
// why the temp?
return arr[j];
}
// Find the position of the lowest element in the set such that x <= arr[pos]
// with a binary search. It requires that the array is sorted.
// Return the value size if all the elements are lower then x
int Sets::getLowerPos( int x ) {
int first = 0, count = size - first, step, pos = 0;
while ( count > 0 ) {
step = count / 2;
pos = first + step;
if ( arr[pos] < x ) {
first = ++pos;
count -= step + 1;
}
else
count = step;
}
return first;
}
// Check if x is present in the set with a binary search.
// It requires that the array is sorted
bool Sets::doesContain( int x ) {
int pos = this->getLowerPos(x);
return ( pos != size && arr[pos] == x );
/*
// Or directly with a simple binary search:
int low = 0, high = size - 1, pos;
while ( low <= high ) {
pos = low + (high - low) / 2;
if ( x == arr[pos] )
return true;
else if ( x < arr[pos] )
high = pos - 1;
else
low = pos + 1;
}
return false;
*/
}
// ... isSubset() and isProper() as above ...
void Sets::printOrderedPairs( const Sets &b){
cout << "A X B = {";
for (int i = 0; i < size; i++){
for (int j = 0; j < b.size; j++){
cout << '(' << arr[i] << ", " << b.arr[j] << "), ";
}
}
cout << "\b\b} ";
}
void Sets::printSet(){
cout << '{';
for (int i = 0; i < size; i++){
cout << arr[i] << ", ";
}
cout << "\b\b} ";
}
int main(void) {
try {
Sets a;
Sets b;
a.addElement(9);
a.addElement(3);
a.addElement(7);
a.addElement(5);
a.addElement(1);
b.addElement(3);
b.addElement(7);
b.addElement(1);
b.addElement(5);
cout << "Set A is ";
a.printSet();
cout << "\nSet B is ";
b.printSet();
cout << "\n\n";
a.printOrderedPairs(b);
cout << "\n\n";
if ( a.isSubset(b) ) {
cout << "Set B is a subset of set A\n";
}
else {
cout << "Set B is not a subset of set A\n";
}
if ( a.isProper(b) ){
cout << "Set B is a proper subset of set A\n";
}
else{
cout << "Set B is not a proper subset of set A\n";
}
system("PAUSE");
}
catch ( const bad_alloc& e) {
cout << "Allocation failed: " << e.what() << '\n';
}
return 0;
}
Now the output is:
Set A is {1, 3, 5, 7, 9}
Set B is {1, 3, 5, 7}
A X B = {(1, 1), (1, 3), (1, 5), (1, 7), (3, 1), (3, 3), (3, 5), (3, 7), (5, 1), (5, 3), (5, 5), (5, 7), (7, 1), (7, 3), (7, 5), (7, 7), (9, 1), (9, 3), (9, 5), (9, 7)}
Set B is subset of set A
Set B is proper subset of set A

Debugging a merge sort

void CensusData::mergeSort(int type) {
if(type == 0)
MERGE_SORT(type, 0, data.size());
}
void CensusData::MERGE_SORT(int type, int p, int r){
//int q;
//cout << "data size " << data.size() << endl;
std::cout << "MERGE_SORT START ///("<< p << ", " << r << ")" <<std::endl;
if(p < r)
{
int q = (p + r)/2;
MERGE_SORT(type, p, q);
MERGE_SORT(type, q + 1, r);
MERGE(type, p, q ,r);
}
}
void CensusData::MERGE(int type, int p, int q, int r){
if(type == 0)
{
std::cout << "MERGING" << std::endl;
//int n1;
//int n2;
int n1 = q - p + 1;
int n2 = r - q;
int L[n1 + 1];
int R[n2 + 1];
for(int i = 1; i < n1; i++)
{
cout << "filling Left Array" << endl;
L[i] = data[p + i - 1]->population;
}
for(int j = 1; j < n2; j++)
{
cout << "filling Right Array" << endl;
R[j] = data[q + j]->population;
}
int i = 1;
int j = 1;
for(int k = p; p < r; p++)
{
cout << "for loop: " << endl;
if(L[i] <= R[j])
{
cout << "TRUE" << endl;
data[k]->population = L[j];
i = i + 1;
}
/*else if(data[k]->population == R[j])
{
cout << "FALSE" << endl;
j = j + 1;
}*/
else
{
data[k]->population = R[j];
j = j + 1;
}
}
}
}
do not worry about type, it wont effect this program at all. basically i am trying to make a merge sort that will take a vector containing an integer, the vector looks like this:
class Record { // declaration of a Record
public:
std::string* city;
std::string* state;
int population;
Record(std::string&, std::string&, int);
~Record();
};
std::vector<Record*> data;
basically i have been trying to get it to actually sort, but it doesn't seem to work at all, i have even seen garbage in the program.
example input:
237 812826 68642
output:
4484540 812826 68642
Note: all of the rest of the program works fine (tested it with an insertion sort) only this part is not working.
Take a look at lecture 15 of the excellent Stanford Universities course Programming Abstractions. It covers all kinds of sorts including merge:
http://see.stanford.edu/see/lecturelist.aspx?coll=11f4f422-5670-4b4c-889c-008262e09e4e
You can even get the source code from SourceForge:
http://sourceforge.net/projects/progabstrlib/files/