Code Monkey home page Code Monkey logo

jagged-arrays's Introduction

/* Jagged-Arrays

Objective: I have implemented a custom data structure called as JaggedArrays in C++. A JaggedArray is a 1D array of n bins, and each bin stores a collection of elements of templated type T. This data structure is helpful to ensure high performance for applications needing frequent read and write access to an organizational information. The JaggedArray class that is implemented has two fundamental representation modes: unpacked and packed. In the unpacked representation, the JaggedArray stores an array of integers containing the counts of how many elements are in each bin and an array of pointers to arrays that hold these elements. In the packed representation, the JaggedArray stores an array of offsets for the start of each bin. These offsets refer to a single large array that stores all of the elements grouped by bin but all packed into the same large array. We can convert a JaggedArray from unpacked to packed mode by calling the pack member function and similarly convert from packed to unpacked by calling unpack.

The member functions used for the implementation include: numElements, numBins, isPacked, addElement, removeElement, pack, unpack and print. */

#ifndef jagged_array_h_ #define jagged_array_h_ #include #include #include using namespace std;

template class JaggedArray { public: //TYPEDEFS typedef unsigned int size_type;

//CONSTRUCTORS, ASSIGNMENT OPERATORS AND DESTRUCTORS
JaggedArray(const int& bins) { this->create(bins); }
JaggedArray() { this->create(); }
JaggedArray(const JaggedArray& v) { this->copy(v); }
JaggedArray<T>& operator=(const JaggedArray<T>& v);
~JaggedArray();//DESTRUCTOR

//ACCESSORS
size_type numElements() const { return num_elements; }
size_type numBins() const {return num_bins; }
int numElementsInBin(int bin_no) const;
T& getElement(int bin_no, int position_in_bin) const;
bool isPacked() const;
void print();
void pack();
void unpack();

//MODIFIERS
void addElement(int position, T element);
void removeElement(int bin_pos, int pos_in_bin);
void clear();

private:

// PRIVATE MEMBER FUNCTIONS
void create();
void create(const int& bins);
void copy(const JaggedArray<T>& v);

// REPRESENTATION
size_type num_elements;
size_type num_bins;
size_type *counts;
T** unpacked_values;
T* packed_values;
size_type *offsets;

};

template void JaggedArray::create() { //initialization of member variables counts = NULL; num_elements = num_bins = 0; unpacked_values=NULL; packed_values=NULL; offsets=NULL; }

template void JaggedArray::create(const int& bins) { //constructor with argument as number of bins offsets=NULL; packed_values=NULL; num_elements=0; num_bins=bins; //creating arrays -counts, unpacked_values counts = new size_type [num_bins]; for(int i=0; i<num_bins;i++) { counts[i]=0; } unpacked_values=new T*[bins];

for(size_type i=0; i<num_bins;i++)
{
    unpacked_values[i]=new T[0];
}

}

template int JaggedArray::numElementsInBin(int bin_no) const{

if(bin_no<0 || bin_no>=num_bins) { cerr<<"cannot find this bin"; exit(1); } if(isPacked()) { if(bin_no==num_bins-1) return num_elements-offsets[bin_no]; else return offsets[bin_no+1]-offsets[bin_no]; } else return counts[bin_no]; }

template bool JaggedArray::isPacked() const{

//checking if packed or unpacked if(counts==NULL && unpacked_values==NULL) return true; else return false; }

template void JaggedArray::addElement(int position, T element){

if(!isPacked())
    {
        if(position>num_bins || position<0)
        {
        cerr<<"no such bin exists:";
        exit(1);
        }
        else
        {
        for(int i=0; i<num_bins; i++)
            {
            if(i==position)
                {
                    T *new_arr= new T[numElementsInBin(i)+1]; 	//creating a new array with extra 1 space
                    for(int j=0;j<numElementsInBin(i);j++)
                    {
                        new_arr[j]=unpacked_values[i][j]; 		//transferring values to a temporary array
                    }
            if(unpacked_values!=NULL)
                {
                delete[] unpacked_values[i]; //deleting the old array
                unpacked_values[i]=NULL;
                }
            unpacked_values[i]=new_arr; 	//pointing the temp array to unpacked_values again which is now updated
            unpacked_values[i][numElementsInBin(i)]=element;
            counts[i]+=1; 			//increasing counters
            num_elements+=1;
                }
            }
        }
    }

else{
    cerr<<"Cannot add elements in packed mode :";
    exit(1);
}

}

template T& JaggedArray:: getElement(int bin_no, int position_in_bin)const{

if(isPacked())
{
    if(bin_no<0 || bin_no>(numBins()-1))        //Error checking
    {
    cerr<<"Incorrect inputs"<<endl;
    exit(1);
    }
    else if(position_in_bin>(numElementsInBin(bin_no)-1) || position_in_bin<0)
    {
    cerr<<"Incorrect inputs"<<endl;
    exit(1);
    }
    else{
    int offset=offsets[bin_no];
    return packed_values[offset+position_in_bin];   //calculating unpacked_values from packed values using offset
    }
}

else{
    if(bin_no<0 || bin_no>(numBins()-1))
    {
    cerr<<"Incorrect inputs"<<endl;
    exit(1);
    }

    else if(position_in_bin>(numElementsInBin(bin_no)-1) || position_in_bin<0)
    {
    cerr<<"Incorrect inputs"<<endl;
    exit(1);
    }
    else
    return unpacked_values[bin_no][position_in_bin];
}

}

template void JaggedArray::unpack(){

if(isPacked())
{
    unpacked_values=new T*[num_bins];
    counts = new size_type [num_bins];
    for(int i=0; i<num_bins;i++)
    {
        counts[i]=0;
    }
    for(int i=0;i<num_bins;i++)
    {
        if(i==num_bins-1)
            counts[i]=num_elements-offsets[i]; //calculating the elements in counts array using offsets and num_elements
        else
            counts[i]=offsets[i+1]-offsets[i];
    }
    for(int i=0;i<num_bins;i++)
        {
        unpacked_values[i]= new T[numElementsInBin(i)];
            for(int j=0; j<counts[i];j++)
            {
                    int offset=offsets[i];
                     unpacked_values[i][j]=packed_values[offset+j];
            }

        }
    if(offsets!=NULL)
    {
    delete [] offsets;
    offsets=NULL;
    }
    if(packed_values!=NULL)
    {
    delete [] packed_values;
    packed_values=NULL;
    }
}

else{ cerr<<"Jagged Array already in unpacked mode"<<endl; exit(1); }

}

template void JaggedArray::pack(){

if(!isPacked())
{
    int temp=0;
    int counter=1;
    if(packed_values==NULL)
    packed_values=new T[num_elements];
    if(offsets==NULL)
    offsets=new size_type [num_bins];
    for(int i=1; i<num_bins;i++)
    {
    offsets[0]=0;
    counter=i;
    while(counter>0)        //calculating the elements to be stored in offsets using counts
    {
        temp+=counts[counter-1];
        counter--;
    }
        offsets[i]=temp;
        temp=0;
        counter=1;
}
int counter1=0;
for(unsigned int i=0; i<num_bins; i++)
    {
    for(unsigned int j=0; j<numElementsInBin(i);j++)
        {
            packed_values[counter1]=unpacked_values[i][j];  //copying the elements in unpacked to packed array
            counter1++;
        }
    }
if(counts!=NULL)
 {
    delete [] counts;
    counts=NULL;
 }

if(unpacked_values!=NULL) { for(int i=0; i<num_bins; i++) { if(unpacked_values[i]!=NULL) delete [] unpacked_values[i]; } delete [] unpacked_values; unpacked_values=NULL; } } else{ cerr<<"Jagged array is already in packed mode"; exit(1); }

} template JaggedArray& JaggedArray::operator=(const JaggedArray& v){

if (this != &v)
 {
    num_elements=v.numElements();
    num_bins=v.numBins();
    if(v.isPacked()==true)
    {
        unpacked_values=NULL;
        counts=NULL;
        delete [] offsets;
        delete [] packed_values;
        offsets=new size_type[num_bins];
        packed_values =new T[num_elements];
        for(int i=0; i<num_bins; i++)
            {
                offsets[i]=v.offsets[i];
            }
        for(int j=0; j<num_elements; j++)
            {
                packed_values[j]=v.packed_values[j];
            }
    }
else
   {
    offsets=NULL;
    packed_values=NULL;
    delete[] counts;
    counts=NULL;
    for(int i=0; i<num_bins; i++)
        {
            delete [] unpacked_values[i];
            unpacked_values[i]=NULL;
        }
        delete [] unpacked_values;
        unpacked_values=NULL;
        counts=new size_type [num_bins];
        unpacked_values=new T*[num_bins];
        for(int i=0; i<num_bins; i++)
            {
                counts[i]=v.numElementsInBin(i);
            }

        for(int i=0; i<num_bins; i++)
            {
                unpacked_values[i]=new T[v.numElementsInBin(i)];
                for(int j=0; j<v.numElementsInBin(i); j++)
                unpacked_values[i][j]=v.getElement(i,j);
            }
    }

}

return *this; }

template void JaggedArray::copy(const JaggedArray& v) {

    num_elements=v.numElements();
    num_bins=v.numBins();
    //copying counts and unpacked values for unpacked array
    if(v.isPacked()==false)
    {
    offsets=NULL;
    packed_values=NULL;
    counts = new size_type [num_bins];
    for(int i=0; i<this->num_bins;i++)
        {
            this->counts[i]=v.counts[i];
        }
    unpacked_values=new T*[num_bins];
    for(size_type i=0; i<this->num_bins;i++)
        {
            this->unpacked_values[i]= new T[numElementsInBin(i)];
            for(unsigned int j=0; j<this->numElementsInBin(i);j++)
                {
                    this->unpacked_values[i][j]=v.getElement(i,j);
                }
        }
    }
else{
        //copying offsets and packed_values for packed array
        unpacked_values=NULL;
        counts=NULL;
        offsets = new size_type[num_bins];
        packed_values=new T [num_elements];
        for(int i=0; i<this->num_bins;i++)
        {
            this->offsets[i]=v.offsets[i];
        }

        for(int i=0; i<this->num_elements;i++)
        {
            this->packed_values[i]=v.packed_values[i];
        }

}

}

template void JaggedArray::print() { if(!isPacked()) { cout<<"num_bins: "<<numBins()<<std::endl; cout<<"num_elements: "<<numElements()<<std::endl; cout<<"counts: "; for(int i=0;i<num_bins;i++) { std::cout<<numElementsInBin(i)<<' '; } std::cout<<std::endl; cout<<"values: "; for(unsigned int i=0; i<num_bins; i++) { for(unsigned int j=0; j<numElementsInBin(i);j++) { cout<<unpacked_values[i][j]<<' '; } } cout<<endl<<endl; }

else{ cout<<"num_bins: "<<numBins()<<std::endl; cout<<"num_elements: "<<numElements()<<std::endl; cout<<"offsets: "; for(int i=0;i<num_bins;i++) { std::cout<<offsets[i]<<' '; } cout<<endl; cout<<"values: ";

for(int i=0;i<num_elements;i++)
    {
    std::cout<<packed_values[i]<<' ';
    }

cout<<endl<<endl; } }

template void JaggedArray:: removeElement(int bin_pos, int pos_in_bin) { if(!isPacked()) { if((bin_pos<0 && bin_pos>num_bins) || (pos_in_bin > numElementsInBin(bin_pos) && pos_in_bin<0)) { cerr<<"Incorrect inputs"<<endl; } else { for(unsigned int j=pos_in_bin+1; j<numElementsInBin(bin_pos);j++) { unpacked_values[bin_pos][j-1]=unpacked_values[bin_pos][j]; } num_elements--; counts[bin_pos]--; } } else{ cerr<<"Cannot remove from a packed jagged array"<<endl; exit(1); } }

template void JaggedArray::clear(){ if(!isPacked()) { num_elements=0; for(int i=0;i<numBins();i++) { counts[i]=0;//putting zeroes in counts for unpacked if(unpacked_values[i]!=NULL) { delete [] unpacked_values[i]; unpacked_values[i]=NULL; } } }

else{ cerr<<"cannot clear a packed array"<<endl; exit(1); }

}

template JaggedArray::~JaggedArray() { delete [] counts; delete [] offsets; delete [] packed_values; if(unpacked_values!=NULL) { for(int i=0; i<num_bins; i++) { delete [] unpacked_values[i]; } delete [] unpacked_values; } counts=NULL; offsets=NULL; packed_values=NULL; unpacked_values=NULL;

}

#endif

jagged-arrays's People

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.