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

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

Related

Program containing threading in cpp is not executed completely

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.

Incorrect Comparisons And Swaps Counter Output for Quicksort Function

Im currently trying to implement a c++ program which compares the number of swaps and comparisons in a variety of different sorting methods. The program appears to be working perfectly for all sorting methods (selection sort, insertion sort) except quicksort which only outputs a comparison and swap count of 0 no matter the data size or order of the list. Ive included the full program below. The quicksort function is definitely working its only the counting element which isn't which is strange since it uses external compare and swap functions which are meant to increment the appropriate counter each time they are called. Any help is greatly appreciated.
#include <cstdlib>
#include <getopt.h>
#include <iostream>
#include <string>
#include<limits>
using namespace std;
unsigned long long comparisons = 0;
unsigned long long swaps = 0;
bool comp_less(int a, int b){
++comparisons;
if ( comparisons == std::numeric_limits<unsigned long long>::max() )
{
std::cout << "Number of comparisons reached max value. Resetting it 0.\n";
swaps = 0;
}
return a < b;
}
void swap(int& a, int& b)
{
++swaps;
if ( swaps == std::numeric_limits<unsigned long long>::max() )
{
std::cout << "Number of swaps reached max value. Resetting it 0.\n";
swaps = 0;
}
int t = a;
a = b;
b = t;
}
void selectionSort(int *first, int *last)
{
for(int *i = first; i < (last - 1); ++i){
int *min = i;
for(int *j = i + 1; j < last; ++j){
if(comp_less(*j, *min)){
min = j;
}
}
swap(*i, *min);
}
}
void insertionSort(int* first, int* last)
{
for (int *i = first + 1; i < last; ++i)
{
int temp = *i;
int *j;
for (j = i; j > first && comp_less(temp, *(j - 1)); --j)
{
swap(*j, *(j - 1));
}
*j = temp;
}
}
int *partition(int *first, int *last)
{
int *pivot = last - 1;
int *i = first;
int *j = last - 1;
for (;;)
{
while (comp_less(*i, *pivot) && i < last)
{
++i;
}
while (*j >= *pivot && j > first)
{
--j;
}
if (i >= j)
break;
swap(*i, *j);
}
swap(*(last - 1), *i);
return i;
}
void quickSort(int* first, int* last) {
{
if ((first - last) <= 1)
return;
int *pivot = partition(first, last);
quickSort(first, pivot);
quickSort(pivot + 1, last);
}
}
int main(int argc, char** argv)
{
string algorithm = "selection";
string dataset = "random";
for (int c; (c = getopt(argc, argv, "ravqsin")) != -1;) {
switch (c) {
case 'r':
dataset = "random";
break;
case 'a':
dataset = "sorted";
break;
case 'v':
dataset = "reverse";
break;
case 'q':
algorithm = "quicksort";
break;
case 's':
algorithm = "selection";
break;
case 'i':
algorithm = "insertion";
break;
case 'n':
algorithm = "none";
break;
}
}
argc -= optind;
argv += optind;
const int size = argc > 0 ? atoi(argv[0]) : 10000;
int* data = new int[size];
if (dataset == "sorted") {
for (int i = 0; i < size; ++i) {
data[i] = i;
}
}
else if (dataset == "reverse") {
for (int i = 0; i < size; ++i) {
data[i] = size - i - 1;
}
}
else if (dataset == "random") {
for (int i = 0; i < size; ++i) {
data[i] = rand() % size;
}
}
if (algorithm == "quicksort") {
quickSort(data, data + size);
}
else if (algorithm == "selection") {
selectionSort(data, data + size);
}
else if (algorithm == "insertion") {
insertionSort(data, data + size);
}
else if (algorithm=="none"){
cout<< "Oops!" <<'\n';
exit(1);
}
cout << "OK" << '\n';
cout << "Algorithm: " << algorithm << '\n';
cout << "Data set: " << dataset << '\n';
cout << "Size: " << size << '\n';
cout << "Swaps: " << swaps << '\n';
cout << "Comparisons: " << comparisons << '\n';
return 0;
}
In your quickSort function, change
if ((first - last) <= 1)
to
if ((last - first) <= 1)

Counter in arrays c++

i have a really simple code right there that counts how much values you need in arrays.
for (int i = 0; i < dm; i++)
{
if (arr[i] == c)
{
counter++;
}
};
But i need to make it a little bit tricky.I need to count number of same values. Imagine i have an array {4,4,4,3,3,2,2,1,1,0,0,0} and i need to find how much "twins" there. So 3,2,1 are twins because they have only 1 exact friend.
I tried something like 2 fors and 2 counters but still have troubles. Thanks. Hope you understand what i mean by "twin". x and x are twins and y,y,y are not ( just in case)
I'd make a map that counts - for each individual number in the array - their occurrences. The code could look as follows:
#include <iostream>
#include <map>
int main()
{
const int numberOfElements = 12;
int array[numberOfElements] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
std::map<int,int> counts;
for (int i=0; i < numberOfElements; i++) {
counts[array[i]]++;
}
for (auto x : counts) {
if (x.second == 2) {
cout << "pair: " << x.first << endl;
}
}
return 0;
}
If - for some reason - the range of the elements is limited, you could also use a "plain" array for counting the occurrences. If, for example, the elements are in the range of 0..4, you could use the following fragment:
const int numberOfElements = 12;
const int elementMax = 4;
int array[numberOfElements] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
int counts[elementMax+1] = {};
for (int i=0; i<numberOfElements; i++) {
counts[array[i]]++;
}
for (int i=0; i <= elementMax; i++) {
if (counts[i] == 2) {
cout << "pair: " << i << endl;
}
}
And if your array is sorted, than a solution without a counter-array could look as follows:
const int numberOfElements = 12;
int array[numberOfElements] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
int prev = -1;
int count = 0;
for (int i=0; i<numberOfElements; i++) {
if (array[i] == prev) {
count++;
}
else {
if (count == 2) {
cout << "pair: " << prev << endl;
}
count=1;
prev = array[i];
}
}
if (prev >= 0 && count==2) {
cout << "pair: " << prev << endl;
}
You can do that in one pass and use binary search for efficiency:
int arr[] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
int twins = 0;
for( auto i = std::begin( arr ); i != std::end( arr ); ) {
auto next = std::upper_bound( i, std::end( arr ), *i, std::greater<int>() );
if( std::distance( i, next ) == 2 ) ++twins;
i = next;
}
Live example
In case there are not too many duplicates in the array std::upper_bound could be not efficient and can be easily replaced:
auto next = std::find_if( std::next( i ), std::end( arr ), [i]( int n ) { return *i != n; } );
Solution without using additional array:
int twins_counter = 0;
for (int i = 0; i < dm; i++)
{
int counter = 0; // counter for elements
for (int j = 0; j < dm; j++)
{
if (arr[i] == arr[j])
{
if( j < i )
{
break; // we have searched twin for this element already
}
counter++;
if( counter > 2 )
{
break; // we meet element third time, it isn't twin
}
}
}
if( counter == 2 )
{
twins_counter++;
}
};
For sorted (upwards or downwards) arrays one cycle is enough:
int twins_counter = 0;
int counter = 1;
for (int i = 1; i < dm; i++)
{
if( arr[i] == arr[i-1] )
{
counter++;
}
else
{
if( counter == 2 )
{
twins_counter++;
counter = 1;
}
}
}
// check last value
if( counter == 2 )
{
twins_counter++;
}

How to apply a flooding algothrim to find the optimal path between a specified source and destination location for a weighted 2D matrix

I've been trying to implement a class which uses a flooding algorithm to generate a list of the indexes for the optimal path between a specified source and destination index.
Such as:
void Dijkstra::findShortestPath(uint sourceIndex, uint destIndex, std::vector<int> & optimalPath);
For example, given a 5x5 2d matrix, find the optimal path between between X and Y:
[1][1][1][1][1]
[1][1][10][10][1]
[X][1][10][Y][1]
[1][1][10][10][1]
[1][1][1][1][1]
Expected result:
start(10)->11->6->1->2->3->4->9->14->13
Where the above index values map to row and column indexes in the matrix:
index = numOfVertices * rowNumber + rowNumber
I have found several different variants, but no implementation yet which does the above.
This algorithim I'm currently trying to extend to this, I found here:
http://www.programming-techniques.com/2012/01/implementation-of-dijkstras-shortest.html?m=1
Though I do not see how a destination node can be specified here, so I am struggling to understand how I can extend this.
My version is below, compiles and runs fine, however you can only specify the source index in the setBoard() function.
Code:
#include <iostream>
#include "stdio.h"
using namespace std;
const int BOARD_SIZE = 5;
const int INFINITY = 999;
class Dijkstra {
private:
int adjMatrix[BOARD_SIZE][BOARD_SIZE];
int predecessor[BOARD_SIZE];
int distance[BOARD_SIZE];
bool mark[BOARD_SIZE];
int source;
int numOfVertices;
public:
int getIndex(int row, int col);
void setBoard();
/*
* Function initialize initializes all the data members at the begining of
* the execution. The distance between source to source is zero and all other
* distances between source and vertices are infinity. The mark is initialized
* to false and predecessor is initialized to -1
*/
void initialize();
/*
* Function getClosestUnmarkedNode returns the node which is nearest from the
* Predecessor marked node. If the node is already marked as visited, then it search
* for another node.
*/
int getClosestUnmarkedNode();
/*
* Function calculateDistance calculates the minimum distances from the source node to
* Other node.
*/
void calculateDistance();
/*
* Function output prints the results
*/
void output();
void printPath(int);
};
int Dijkstra::getIndex(int row, int col)
{
return numOfVertices * row + col;
}
void Dijkstra::setBoard()
{
source = 0;
numOfVertices = BOARD_SIZE;
cout << "Setting board..." << numOfVertices << " source: " << source << "\n";
for (int i = 0; i < numOfVertices; i++)
{
for (int j = 0; j < numOfVertices; j++)
{
if (getIndex(i, j) == 7 || getIndex(i, j) == 8 || getIndex(i, j) == 12 || getIndex(i, j) == 17 || getIndex(i, j) == 18)
{
adjMatrix[i][j] = 10;
}
else
{
adjMatrix[i][j] = 1;
}
}
}
// print board
printf("\n");
printf("\n");
for (int i = 0; i < numOfVertices; i++)
{
for (int j = 0; j < numOfVertices; j++)
{
if (j == 0)
{
printf("\n");
}
if (source == getIndex(i, j))
{
printf("[X]");
}
else
{
printf("[%d]", adjMatrix[i][j]);
}
}
}
printf("\n");
printf("\n");
}
void Dijkstra::initialize()
{
for (int i = 0; i < numOfVertices; i++)
{
mark[i] = false;
predecessor[i] = -1;
distance[i] = INFINITY;
}
distance[source] = 0;
}
int Dijkstra::getClosestUnmarkedNode()
{
int minDistance = INFINITY;
int closestUnmarkedNode;
for (int i = 0; i < numOfVertices; i++)
{
if ((!mark[i]) && ( minDistance >= distance[i]))
{
minDistance = distance[i];
closestUnmarkedNode = i;
}
}
return closestUnmarkedNode;
}
void Dijkstra::calculateDistance()
{
int minDistance = INFINITY;
int closestUnmarkedNode;
int count = 0;
while (count < numOfVertices)
{
closestUnmarkedNode = getClosestUnmarkedNode();
mark[closestUnmarkedNode] = true;
for (int i = 0; i < numOfVertices; i++)
{
if ((!mark[i]) && (adjMatrix[closestUnmarkedNode][i] > 0) )
{
if (distance[i] > distance[closestUnmarkedNode] + adjMatrix[closestUnmarkedNode][i])
{
distance[i] = distance[closestUnmarkedNode] + adjMatrix[closestUnmarkedNode][i];
predecessor[i] = closestUnmarkedNode;
}
}
}
count++;
}
}
void Dijkstra::printPath(int node)
{
if (node == source)
{
cout << (char) (node + 97) << "..";
}
else if (predecessor[node] == -1)
{
cout << "No path from “<<source<<”to " << (char) (node + 97) << endl;
}
else
{
printPath(predecessor[node]);
cout << (char) (node + 97) << "..";
}
}
void Dijkstra::output()
{
for (int i = 0; i < numOfVertices; i++)
{
if (i == source)
{
cout << (char) (source + 97) << ".." << source;
}
else
{
printPath(i);
}
cout << "->" << distance[i] << endl;
}
}
int main()
{
Dijkstra G;
G.setBoard();
G.initialize();
G.calculateDistance();
G.output();
return 0;
}
Once, in void Dijkstra::calculateDistance(), you do
mark[closestUnmarkedNode] = true;
You have the shortest path from source to closestUnmarkedNode.
So you may add just after
if (closestUnmarkedNode == destNode) {
return;
}
to stop the flood fill.
You will have shortest path for all visited nodes including destNode

C++ Passing class Object to function

I'm new to C++ programming.
Now I have the state class. I want to create neighboring states with this class, so I add the function getNeighboringStates() to my class. In this function I pass in "neighboring_states" to function set_neighboring_state(), this function change "neighboring_states"'s value.
In this function, I set a for loop to test. It print out "7 1 0 3 6 4 5 2 8", which is the value I want. But In the function getNeighboringStates(), I also set a for loop that has the same mission as in set_neighboring_state(), but the screen display "0 1 4716672 2686652 2686528 0 4716676 4519501 4716676".
I don't know what's wrong with my code. What do I need to do now?
int n; // The number of columns as well as rows of the board
int k; // The kind of heuristic function to use
int tilesCount; // The number of tiles, including the blank one
int statesCount; // The number of states generated
int* m_initTiles;
int* m_goalTiles;
int tmpTile;
const int UP = 0;
const int DOWN = 1;
const int RIGHT = 2;
const int LEFT = 3;
int* direction;
class State {
public:
State(){}
int getBlankTilePosition() {
for (int i = 0; i < n * n; i++) {
if (stateTiles[i] == 0)
return i;
}
}
void set_neighboring_state(State* neighboring_state, int direction) {
int blankPosition = getBlankTilePosition();
int neighbor_tiles[n * n];
for (int i = 0; i < n * n; i++) {
neighbor_tiles[i] = getStateTiles()[i];
}
switch(direction) {
case UP:
if (blankPosition/n < 1) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition - n]);
neighboring_state->set_tiles(neighbor_tiles);
// This for loop print out "7 1 0 3 6 4 5 2 8"
for (int i = 0; i < n * n; i++)
cout << neighboring_state.getStateTiles()[i] << " "; cout << endl;
}
break;
case DOWN:
if (blankPosition/n == n - 1) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition + n]);
neighboring_state->set_tiles(neighbor_tiles);
}
break;
case LEFT:
if (blankPosition % n == 0) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition - 1]);
neighboring_state->set_tiles(neighbor_tiles);
}
break;
default:
if ((blankPosition + 1) % n == 0) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition + 1]);
neighboring_state->set_tiles(neighbor_tiles);
}
break;
}
}
/*
The maximum number of neighboring state that can be created is 4.
This function return the neighboring states of a certain state.
The first state represents for the "left" neighbor, the second,
the third and the fourth represent the "right", "up, and "down"
neighbor, respectively.
*/
State* getNeighboringStates() {
State* neighboring_states;
neighboring_states = new State[4];
for (int i = 0; i < 4; i++)
set_neighboring_state(&neighboring_states[i], direction[i]);
// This print out "0 1 4716672 2686652 2686528 0 4716676 4519501 4716676"
cout << endl;
for (int i = 0; i < n * n; i++)
cout << neighboring_states[0].getStateTiles()[i] << " ";
cout << endl;
return neighboring_states;
}
State(int* pStateTiles) {
stateTiles = pStateTiles;
}
void set_tiles(int* tiles) {
stateTiles = tiles;
}
int* getStateTiles() {
return stateTiles;
}
private:
int* stateTiles;
};
void input(const char* fileName) {
ifstream fin;
fin.open(fileName);
// read n, k from file
fin >> n >> k;
// allocate m_initTiles and m_goalTiles memory
m_initTiles = new int[n * n];
m_goalTiles = new int[n * n];
for (int i = 0; i < n * n; i++)
fin >> m_initTiles[i];
for (int i = 0; i < n * n; i++)
fin >> m_goalTiles[i];
for (int i = 0; i < n * n; i++)
cout << m_initTiles[i] << " ";
cout << endl;
for (int i = 0; i < n * n; i++)
cout << m_goalTiles[i] << " ";
cout << endl;
fin.close();
}
void initDirection() {
direction = new int[4];
direction[0] = UP;
direction[1] = DOWN;
direction[2] = RIGHT;
direction[3] = LEFT;
}
int main() {
input("nPuzzle.inp");
initDirection();
State init_state (m_initTiles);
State goal_state (m_goalTiles);
State* init_neighbor = init_state.getNeighboringStates();
// int* state_tile = init_neighbor[0].getStateTiles();
// for (int i = 0; i < n * n; i++)
// cout << state_tile[i] << " ";
return 0;
}
int blankPosition = getBlankTilePosition();
int neighbor_tiles[n * n];
Remove int neighbor_tiles[n * n]; line from above code segment and make it global available to all function , so declare it as data of a class not for function i.e. add int neighbor_tiles[n * n]; to class as an data type .