C++ having problems with PThreads, not compiling - c++

The following function seems to be the cause of the problem"
template <class Type>
void * server_work(void * arg)
{
int ii;
int cno;
Server<Type> * server = (Server<Type> *) arg;
Customer<Type> newcust;
for(ii=0; ii<QUEUE_LENGTH; ii++)
{
size_t length = rand()%(MAX_RANGE-MIN_RANGE)+MIN_RANGE ; // Generate the number, assign to variable.
pthread_mutex_lock(&MUTEX);
cno=CUSTOMER_COUNT;
CUSTOMER_COUNT++;
pthread_mutex_unlock(&MUTEX);
newcust=Customer<Type>(cno, cno,cno,length);
if(CUSTOMER_COUNT<=QUEUE_LENGTH)
{
server->IncreaseNumOfCustomers();
for(size_t i = 0; i < length; ++i)
{
newcust.getLinkedList().insertFirst(1000);
}
server->getCustomers()[ii]=newcust;
}
else
{
break;
}
}
return NULL;
}
The problem occurs when the compiler reads the following bit of code:
int main(int argc, char** argv)
{
pthread_t threads[NUMBER_OF_SERVERS];
int i,j;
if(pthread_mutex_init(&MUTEX, NULL))
{
cout<<"Unable to initialize a MUTEX"<<endl;
return -1;
}
Server<int> servs[NUMBER_OF_SERVERS];
for(i = 0; i < NUMBER_OF_SERVERS; i++)
{
servs[i].setServerNum(i);
pthread_create(threads+i, NULL, server_work, (void *)&servs[i]);//<<--compiler flags here
}
// Synchronization point
for(i = 0; i < NUMBER_OF_SERVERS; i++)
{
pthread_join(*(threads+i), NULL);
}
cout<<"SERVER-NO\tCUSTOMER-NO\tARRIVAL-TIME\tWAITING-TIME\tTRANSACTION-TIME"<<endl;
for(i = 0; i < NUMBER_OF_SERVERS; i++)
{
for(j=0; j<servs[i].getCustomersServed(); j++)
{
cout<<i<<"\t\t"<<servs[i].getCustomers()[j].getCustomerNumber()<<"\t\t"<<servs[i].getCustomers()[j].getArrivalTime()<<"\t\t"<<servs[i].getCustomers()[j].getWaitingTime()<<"\t\t"<<servs[i].getCustomers()[j].getTransactionTime()<<endl;
}
}
cout<<endl;
cout<<endl;
I get the following error from the compiler:
main.cpp:84:71: error: no matches converting function ‘server_work’ to type ‘void* ()(void)’
main.cpp:26:8: error: candidate is: template void* server_work(void*)

You have wrong prototype:
template <class Type>
void * server_work(void * arg)
While pthread is expecting something like this
void * server_work(void * arg)
However it's not so hard to workaround this, for instance:
void* CoolWrapper(void* arg)
{
return server_work<desired_type>(arg);
}

Related

C++ Error - passing 'const Dataset<double>' as 'this' argument discards qualifiers[-fpermissive]

I have a class Dataset as given below
template <class StorageType> class Dataset
{
private:
class Row
{
private:
uInt32 NCol;
StorageType *Data;
public:
Row(){
Data = NULL;
}
void SetCol(uInt32 Col){
if((Data = new StorageType[Col]) == NULL)
{
cout << "Dataset::memory exhausted ... exiting" << endl;
exit(1);
}
NCol = Col;
}
~Row(){
if(Data != NULL)
{
delete []Data;
}
}
StorageType &operator[](uInt32 Col){
return Data[Col];
}
};
Row *Array;
uInt32 NRow;
uInt32 NCol;
public:
Dataset(uInt32 Row, uInt32 Col)
{
if((Array = new Row[Row]) == NULL){
cerr << "Dataset::memory exhausted ... exiting" << endl;
exit(1);
}
register uInt32 i;
for(i = 0;i < Row;i++)
{
Array[i].SetCol(Col);
}
NRow = Row;
NCol = Col;
}
Dataset(Dataset<StorageType> &B)
{
NRow = B.GetNoOfRows();
NCol = B.GetNoOfCols();
if((Array = new Row[NRow]) == NULL){
cerr << "Martix::memory exhausted ... exiting" << endl;
exit(1);
}
register uInt32 i,j;
for(i = 0;i < NRow;i++)
{
Array[i].SetCol(NCol);
for(j = 0;j < NCol;j++)
{
Array[i][j] = B[i][j];
}
}
}
virtual ~Dataset()
{
delete[] Array;
}
Row &operator[](uInt32 Row){
return Array[Row];
}
uInt32 GetNoOfRows() const
{
return NRow;
}
uInt32 GetNoOfCols() const
{
return NCol;
}
Dataset<StorageType> operator*(Dataset<StorageType> const &B)
{
Dataset<StorageType> Temp(NRow,B.GetNoOfCols());
if(NCol == B.GetNoOfRows())
{
uInt32 Row = B.GetNoOfRows();
uInt32 Col = B.GetNoOfCols();
register uInt32 i, j, k;
register StorageType Product;
for(i = 0;i < NRow;i++)
{
for(j = 0;j < Col;j++)
{
Product = 0;
for(k = 0;k < Row;k++)
{
Product += Array[i][k]*B[k][j]; **--> error here**
}
Temp[i][j] = Product;
}
}
}
else
{
cerr << "Dataset::matrices aren't compatible for multiplication" << endl;
}
return (Temp);
}
void operator=(Dataset<StorageType> const &B)
{
register uInt32 i, j;
uInt32 Row = B.GetNoOfRows();
uInt32 Col = B.GetNoOfCols();
for(i = 0;i < Row;i++)
{
for(j = 0;j < Col;j++)
{
Array[i][j] = B[i][j]; **--> error here**
}
}
}
};
I am getting the following error
passing 'const Dataset' as 'this' argument discards
qualifiers[-fpermissive]
at the places marked --> error here.
.
I need to multiply two Dataset from a caller class, using operator*, and making the argument const is mandatory. How do I resolve it? Some code example will be helpful.
The code you presented produces a lot more errors, so it cannot have produced only the errors you show.
After fixing the fairly trivial problems the code compiles just fine (until recent compilers start to complain about the forbidden register storage class which I have last used about 1988), see https://godbolt.org/z/56necn4rd .
Clean up your code and present the errors that remain, if any.
I noticed that the error appears to be related to the fact that your class Datasetis a template. A non-templated version of the same class (where I simply replaces StorageType with int) leads to the expected error (calling a non-const member function from a const object).
The reason appears to be that the error only occurs when the template code is actually instantiated, that is, if some code actually calls the const-violating function, directly or indirectly. Here is an example (live at godbolt)).
Technically, the definition of f() is a const violation because the body calls g() from an object that is not const. (The reason this is forbidden is because g() might change the object which the const f() promises not to do.) But templates are special — for example, the SFINAE pattern makes it possible to have code that normally would create a compiler error when creating the list of potential overloads in templates for a given template parameter; those overloads are simply discarded at instantiation time. Something similar may be in play here; it's just that none of the overloads is viable, but that is only detected (and relevant) at instantiation time.
#include <iostream>
using namespace std;
template<class T> struct TC
{
void g() {}
// We can violate constness in member functions in templates
// as long as nobody calls them:
void f(const TC<T> &crtc) const { crtc.g(); }
};
int main()
{
TC<int> tc;
const TC<int> &crtc = tc;
// crtc.f(crtc); // <-- comment this in to get the error.
}

Array of functions where i-th element returns i

Yesterday my friend challenged me to write a function in C which would return an array of function pointers where i-th function would return i.
It is easy to get a similar effect in C++, but I am not sure how to do it in C.
Can anyone help me with that?
Edit.
The effect that I am looking for is something equivalent to this.
vector <function<int()>> get_functions(int n) {
vector <function<int()>> functions;
for (int i = 0; i < n; ++i) {
functions.emplace_back([i]() {
return i;
});
}
return functions;
}
int main() {
auto functions = get_functions(10);
for (auto f:functions) {
cout << f() << endl;
}
return 0;
}
Edit.
As asked in the comment section I provide my poor attempt on the challenge.
typedef int (*fun_t)(void);
int fun() { return 0; }
int fun1() { return 1; }
fun_t *get_functions() {
fun_t *functions = malloc(sizeof(fun_t) * 2);
functions[0] = fun;
functions[1] = fun1;
return functions;
}
int main() {
fun_t* funs=get_functions();
for (int i = 0; i < 2; ++i) {
printf("%d\n",funs[i]());
}
free(funs);
}
The C++ code is cheating. function<int()> is not a function pointer; in fact, it's not a pointer at all, it's a class.
Therefore the equivalent C code would look something like this:
#include <stdio.h>
#include <stdlib.h>
// function<int ()>, simplified version just for this task
typedef struct {
int (*code)(int);
int ctx;
} function_int_t;
// function<int()>::operator()()
int call(function_int_t fun) {
return fun.code(fun.ctx);
}
// lambda body
int proto(int ctx) {
return ctx;
}
function_int_t *get_functions(size_t n) {
function_int_t *functions = calloc(n, sizeof *functions);
if (!functions) {
abort(); // hey, that's how C++ does it
}
for (size_t i = 0; i < n; i++) {
functions[i] = (function_int_t){ proto, i }; // capture i
}
return functions;
}
int main(void) {
size_t n = 10;
function_int_t *functions = get_functions(n);
for (size_t i = 0; i < n; i++) {
printf("%d\n", call(functions[i]));
}
free(functions);
return 0;
}

Refactoring Ideas for generic objects buffer in c++

I am trying to come up with a generic buffer (or heap container - not sure how to call it) for generic objects. So I could have a large number of them in contiguous memory.
The header I did works, but I was wondering if you guys could help me understand what am I doing wrong if anything, or any gotchas/bugs I am missing here. Or any other re-factoring I could do to make it better.
buffer.h
#ifndef _ENGINE_BUFFER
#define _ENGINE_BUFFER
#include <cstdlib>
#include <cstdio>
#include <typeinfo>
#include <cstring>
// Defining buffer struct:
template <typename T>
struct Buffer {
unsigned int _size;
unsigned int _number_of_objects;
unsigned int _head;
unsigned int _next;
unsigned int * _backlog;
int _backlog_head;
T* _buffer_address;
};
// Creating buffer:
template <typename T>
Buffer<T>* createBuffer(int size) {
Buffer<T>* _buffer = (Buffer<Sprite>*) calloc(1, sizeof(Buffer<T>));
if (_buffer) {
*(_buffer) = Buffer<T>();
_buffer->_size = size;
_buffer->_number_of_objects = 0;
_buffer->_head = 0;
_buffer->_next = 0;
_buffer->_backlog = (unsigned int*) calloc(size, sizeof(int));
_buffer->_backlog_head = -1;
_buffer->_buffer_address = (T*) calloc(size, sizeof(T));
if(_buffer->_buffer_address) {
return _buffer;
}
}
return (Buffer<T>*) nullptr;
}
// Adding object to buffer:
template <typename T>
int addObjectToBuffer(Buffer<T>* _buffer, const T &_obj) {
int _head = 0;
if (_buffer->_backlog_head > -1) {
_buffer->_buffer_address[_buffer->_backlog[_buffer->_backlog_head]] = _obj;
_head = _buffer->_backlog_head;
_buffer->_backlog_head--;
_buffer->_number_of_objects++;
} else {
if ( (int) (_buffer->_number_of_objects + 1) >= _buffer->_size){
T* _new_address = (T*) calloc((_buffer->_number_of_objects + 1) * 2, sizeof(T));
memcpy(_new_address, _buffer->_buffer_address, _buffer->_number_of_objects * sizeof(T));
free(_buffer->_buffer_address);
_buffer->_buffer_address = _new_address;
_buffer->_size = (_buffer->_number_of_objects + 1) * 2;
for (int i = _buffer->_head; i < _buffer->_size; i++){
_buffer->_buffer_address[i] = 0;
}
}
_buffer->_buffer_address[_buffer->_head] = _obj;
_buffer->_number_of_objects++;
_head = _buffer->_head;
_buffer->_head++;
}
return _head;
}
// Getting number of objects in buffer:
template <typename T>
unsigned int bufferGetSize(Buffer<T>* _buffer) {
return (int) _buffer->_number_of_objects;
}
// Getting next object in buffer:
template <typename T>
T* bufferGetNext(Buffer<T>* _buffer) {
if (_buffer->_backlog_head > -1){
for (int i = 0; i <= _buffer->_backlog_head; i++ ) {
if (_buffer->_backlog[i] == _buffer->_next) _buffer->_next++;;
}
}
unsigned int _next = _buffer->_next;
if (_next < _buffer->_head) {
_buffer->_next++;
return &_buffer->_buffer_address[_next];
} else {
_buffer->_next = 0;
bufferGetNext(_buffer);
}
}
// Reset iterator head:
template <typename T>
void bufferResetHead(Buffer<T>* _buffer){
_buffer->_next = 0;
}
// Deleting object from buffer:
template <typename T>
void deleteObjectFromBuffer(Buffer<T>* _buffer, unsigned int _obj_index) {
if (_obj_index >= 0 && _obj_index <= _buffer->_head) {
bool _obj_exists = false;
for (int i = _buffer->_backlog_head; i >= 0; i-- ) {
if (_buffer->_backlog[i] == _obj_index){
_obj_exists = true;
fprintf(stderr, "\n[ Warning: object_deleted_twice | buffer: %#010x | object: %#010x | index: \"%d\" ]\n",
_buffer, &_buffer->_buffer_address[_obj_index], _obj_index);
}
}
if (!_obj_exists) {
_buffer->_backlog_head++;
_buffer->_backlog[_buffer->_backlog_head] = _obj_index;
_buffer->_number_of_objects--;
}
} else {
fprintf(stderr, "\n[ Warning: index_out_of_range | buffer: %#010x | index: \"%d\" ]\n",
_buffer, _obj_index);
}
}
// Deleting buffer:
template <typename T>
void deleteBuffer(Buffer<T>* _buffer) {
free(_buffer->_buffer_address);
free(_buffer);
}
// Print buffer memory:
template <typename T>
void printBufferMemory(Buffer<T>* _buffer, unsigned int _number_of_columns, bool _print_address) {
int _column_count = 0;
printf("\n");
printf("[ Number of objects in buffer: %#02d | Actual buffer size: %#02d ]\n", _buffer->_number_of_objects, _buffer->_size);
for (int i = 1; i < 11 * _number_of_columns; i++) {
printf("=");
}
printf("\n");
for (int i = 0; i < _buffer->_size; i++) {
if (_column_count > _number_of_columns - 1) {
printf("\n");
_column_count = 0;
}
if (_print_address) {
printf("%#010x ", &_buffer->_buffer_address[i]);
} else {
printf("%#010d ", *(&_buffer->_buffer_address[i]));
}
_column_count++;
}
printf("\n");
for (int i = 1; i < 11 * _number_of_columns; i++) {
printf("=");
}
printf("\n");
}
#endif // _ENGINE_BUFFER
sprite.h
#ifndef _SPRITE
#define _SPRITE
struct Sprite {
int value = 0;
Sprite(int n){
value = n;
}
};
#endif // _SPRITE
main.cpp
#include <cstdio>
#include <cstdlib>
#include "sprite.h"
#include "buffer.h"
using namespace std;
int main()
{
int buffer_size = 512;
int object_number = 512;
Buffer<Sprite>* engine_buffer = createBuffer<Sprite>(buffer_size);
for (int i = 0; i < object_number; i++) {
addObjectToBuffer(engine_buffer, Sprite(i + 100));
}
for (int i = 0; i < bufferGetSize(engine_buffer); i++) {
printf("Value of Sprite %d is: %d\n", i + 1, bufferGetNext(engine_buffer)->value);
}
printBufferMemory(engine_buffer, 10, false);
deleteBuffer(engine_buffer);
return(0);
}

Memory leak concerns

I find myself in a difficult situation. I have a program which is supposed to delete any memory that is dynamically allocated, but whenever I try to call the relevant methods, it comes up with a memory heap corruption.
It seems to work when I don't call the methods, but then I've probably caused a ton of memory leaks. Would anyone have any idea what is going on?
The code is below:
CSVFile.h:
#pragma once
class InputPattern;
class OutputPattern;
class CSVFile
{
private:
const int NAME_MAX = 100;
char* name;
char** buffer;
bool loadedFlag;
int patternCount;
InputPattern** inputs;
OutputPattern** outputs;
void setLoadedFlagTrue();
void setLoadedFlagFalse();
public:
CSVFile();
~CSVFile();
CSVFile(const char*);
void setName(const char*);
char* getFilename(char*, int);
bool getLoadedFlag();
int loadFile();
InputPattern* getInputPattern(int);
OutputPattern* getOutputPattern(int);
void addInputPattern(InputPattern*);
void addOutputPattern(OutputPattern*);
void deleteInputPattern();
void deleteOutputPattern();
void printMetaData();
void printPatterns();
void deleteBuffer();
};
CSVFile.cpp:
#include "CSVFile.h"
#include "InputPattern.h"
#include "OutputPattern.h"
#include <stdio.h>
#include <string.h>
void CSVFile::setLoadedFlagTrue()
{
loadedFlag = true;
}
void CSVFile::setLoadedFlagFalse()
{
loadedFlag = false;
}
CSVFile::CSVFile()
{
name = NULL;
buffer = NULL;
inputs = NULL;
outputs = NULL;
patternCount = 0;
inputs = new InputPattern*[10];
outputs = new OutputPattern*[10];
buffer = new char*[4];
int i;
for (i = 0; i < 10; i++)
{
inputs[i] = new InputPattern();
outputs[i] = new OutputPattern();
buffer[i] = new char[NAME_MAX];
}
}
CSVFile::~CSVFile()
{
delete name;
name = NULL;
}
CSVFile::CSVFile(const char * filename)
{
name = NULL;
buffer = NULL;
inputs = NULL;
outputs = NULL;
patternCount = 0;
inputs = new InputPattern*[10];
outputs = new OutputPattern*[10];
int i;
for (i = 0; i < 10; i++)
{
inputs[i] = new InputPattern();
outputs[i] = new OutputPattern();
}
name = new char[NAME_MAX];
strcpy(name, filename);
}
void CSVFile::setName(const char * filename)
{
name = new char[NAME_MAX];
strcpy(name, filename);
}
char* CSVFile::getFilename(char * outBuff, int outBuffSize)
{
outBuff = new char[outBuffSize + 1];
strncpy(outBuff, name, outBuffSize);
return outBuff;
}
bool CSVFile::getLoadedFlag()
{
if (name == NULL)
{
setLoadedFlagFalse();
return loadedFlag;
}
if (patternCount == 10)
setLoadedFlagTrue();
else
setLoadedFlagFalse();
return loadedFlag;
}
int CSVFile::loadFile()
{
FILE* f;
if ((f = fopen(name, "r")) == NULL)
{
printf("File failed to open\n");
return 0;
}
for (patternCount = 0; patternCount < 4; patternCount++)
{
fgets(buffer[patternCount], 100, f);
}
patternCount = 0;
/*ask about input interaction; potentially remove these variables afterwards*/
float tIn, rIn, gIn, bIn, tOut, oOut;
/*might change this to make it more flexible*/
while (patternCount < 10)
{
fscanf(f, "%f,%f,%f,%f,%f,%f", &tIn, &rIn, &gIn, &bIn, &tOut, &oOut);
printf("%f,%f,%f,%f,%f,%f\n", tIn, rIn, gIn, bIn, tOut, oOut);
inputs[patternCount]->setT(tIn);
inputs[patternCount]->setR(rIn);
inputs[patternCount]->setG(gIn);
inputs[patternCount]->setB(bIn);
outputs[patternCount]->setT(tOut);
outputs[patternCount]->setO(oOut);
patternCount++;
}
fclose(f);
return patternCount;
}
InputPattern * CSVFile::getInputPattern(int index)
{
if (index >= 0 && index < 10)
return inputs[index];
else
return 0;
}
OutputPattern * CSVFile::getOutputPattern(int index)
{
if (index >= 0 && index < 10)
return outputs[index];
else
return 0;
}
void CSVFile::addInputPattern(InputPattern * in)
{
inputs[patternCount] = in;
patternCount++;
}
void CSVFile::addOutputPattern(OutputPattern * out)
{
outputs[patternCount] = out;
patternCount++;
}
void CSVFile::deleteInputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete inputs[i];
}
delete inputs;
inputs = NULL;
}
void CSVFile::deleteOutputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete outputs[i];
}
delete outputs;
outputs = NULL;
}
void CSVFile::printMetaData()
{
int i;
for (i = 0; i < 4; i++)
{
printf("%s", buffer[i]);
}
}
void CSVFile::printPatterns()
{
/*to be completed*/
int i;
for (i = 0; i < patternCount; i++)
{
printf("Class number %d\n", i + 1);
printf("T in = %f\n", inputs[i]->getT());
printf("R in = %f\n", inputs[i]->getR());
printf("G in = %f\n", inputs[i]->getG());
printf("B in = %f\n", inputs[i]->getB());
printf("T out = %f\n", outputs[i]->getT());
printf("O out = %f\n", outputs[i]->getO());
}
}
void CSVFile::deleteBuffer()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete buffer[i];
}
delete buffer;
buffer = NULL;
}
TestHarness.cpp sample (this is executed in the main function)
bool TestHarness::testCSVFileSetFilepath() /*this works fine*/
{
bool testResult = false;
CSVFile* test = NULL;
test = new CSVFile();
char *testName = NULL;
test->setName("test.txt");
testName = test->getFilename(testName, 10);
if (strcmp("test.txt", testName) == 0)
testResult = true;
delete test;
delete testName;
test = NULL;
testName = NULL;
return testResult;
}
...........................
bool TestHarness::testCSVFileLoadFile() /*this causes the corruption*/
{
bool testResult = false;
CSVFile* test = NULL;
test = new CSVFile();
test->setName("C:/Users/user/Documents/AssignmentsSem2/ExampleFile.csv");
if (test->loadFile() == 10)
testResult = true;
test->deleteInputPattern();
test->deleteOutputPattern();
test->deleteBuffer(); /*these three above methods are the ones I'm talking about*/
delete test;
test = NULL;
return testResult;
}
You can check for memory leaks with
#define _CRTDBG_MAP_ALLOC
#include<crtdbg.h>
struct AtExit
{
~AtExit()
{
_CrtDumpMemoryLeaks();
}
}doAtExit;
just outside the main method.
This runs whenever your program ends. All it really does is display whether you have a memory leak or not. Doesn't help with actually finding them.
You might need Visual Studio for this.
This is how it looks when a memory leak is found

Disjoint Set ADT Implementation in C++

I have problem in implementing a disjoint set ADT in C++ due to the fact that our teacher only explained the union and find operations. I fully understand the concepts of union and find but I am still confused about how to implement them.
Could someone please give me an idea of the implementation and also explain what the interface of this data structure should look like?
You have way too many requirements, we're not here to do your homework for you.
Have a look at http://en.wikipedia.org/wiki/Disjoint-set_data_structure
#include <iostream>
template<typename T>
class Disjoint_sets
{
public:
int FIND(int pos);
bool in_same_set(T data_element_1, T data_element_2);
void UNION_IF_EQUIVALENT(T data_element_1, T data_element_2);
void UNION(T data_element_1, T data_element_2);
Disjoint_sets(bool (*is_equivalent)(T, T));
Disjoint_sets();
Disjoint_sets(T* data_arr, bool (*is_equivalent)(T, T),int size);
void insert(T data_element);
bool is_root(int pos_number);
int get_pos(T data_element);
void partition();
void print_partition();
private:
T* data;
int* parent_pos;
int* number_of_children;
int size;
bool (*isequivalent)(T D1, T D2);
};
template<typename T>
Disjoint_sets<T>::Disjoint_sets()
{
data = NULL;
parent_pos = NULL;
number_of_children = NULL;
size = 0;
isequivalent = NULL;
}
template<typename T>
Disjoint_sets<T>::Disjoint_sets(bool (*is_equivalent)(T, T))
{
isequivalent = is_equivalent;
data = NULL;
parent_pos = NULL;
number_of_children = NULL;
size = 0;
}
template<typename T>
Disjoint_sets<T>::Disjoint_sets(T* data_arr, bool (*is_equivalent)(T, T), int size)
{
data = new T[size];
parent_pos = new int[size];
number_of_children = new int[size];
this->size = size;
isequivalent = is_equivalent;
for (int i = 0; i < size; i++)
{
data[i] = data_arr[i];
parent_pos[i] = -1;
number_of_children[i] = 0;
}
}
template<typename T>
bool Disjoint_sets<T>::is_root(int pos)
{
if (pos<0 && pos>size - 1)
{
std::cout << "Error, invalid pos supplied to is_root\n";
return false;
}
if (parent_pos[pos] == -1)
{
return true;
}
else
{
return false;
}
}
template <typename T>
int Disjoint_sets<T>::FIND(int pos)
{
while (!is_root(pos))
{
pos = parent_pos[pos];
}
return pos;
}
template<typename T>
bool Disjoint_sets<T>::in_same_set(T data_element_1, T data_element_2)
{
return FIND(get_pos(data_element_1)) == FIND(get_pos(data_element_2));
}
template<typename T>
int Disjoint_sets<T>::get_pos(T data_element)
{
for (int i = 0; i < size; i++)
{
if (data[i] == data_element)
{
return i;
}
}
std::cout << "Could not find element\n";
return -1;
}
template <typename T>
void Disjoint_sets<T>::UNION(T data_element_1, T data_element_2)
{
int data_parent_1_pos = FIND(get_pos(data_element_1));
int data_parent_2_pos = FIND(get_pos(data_element_2));
if ( data_parent_1_pos==data_parent_2_pos )
{
return;
}
if (number_of_children[data_parent_1_pos] >= number_of_children[data_parent_2_pos])
{
parent_pos[data_parent_2_pos] = data_parent_1_pos;
}
else
{
parent_pos[data_parent_1_pos] = data_parent_2_pos;
}
}
template <typename T>
void Disjoint_sets<T>::UNION_IF_EQUIVALENT(T data_element_1, T data_element_2)
{
if (FIND(get_pos(data_element_1)) == FIND(get_pos(data_element_2)))
{
return;
}
if (isequivalent(data_element_1, data_element_2))
{
UNION(data_element_1, data_element_2);
}
}
template<typename T>
void Disjoint_sets<T>::partition()
{
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
UNION_IF_EQUIVALENT(data[i], data[j]);
}
}
}
template <typename T>
void Disjoint_sets<T>::print_partition()
{
for (int i = 0; i < size; i++)
{
if (is_root(i))
{
for (int j = 0; j < size; j++)
{
if (FIND(j) == i)
{
std::cout << data[j] << " ";
}
}
}
std::cout << "\n";
}
}
template <typename T>
bool lol(int a, int b)
{
return a * a == b * b;
}
int main()
{
int arr[6] = { -1,1,2,3,-3,4 };
Disjoint_sets<int> d(arr,lol<int>, 6);
d.partition();
d.print_partition();
}