mapping of n-dimension array to 1d-array plus operations on array mapping

main.cpp:


#include "Arrays.h"
#include<iostream>
using namespace std;

int main()
{
    int rows = 5, cols = 5;
    Arrays<int> testArr(rows, cols);

    //intialisations of test array.
    int **arrInt = new int *[rows];
    for(int i = 0; i < rows; ++i)
        arrInt[i] = new int[cols];

    srand(rows + cols);
    for(int i = 0; i < rows; ++i)
        for(int j = 0; j < cols; ++j)
            arrInt[i][j] = 1 + rand() % 45;

    testArr.feedInitData(rows, cols, arrInt);
    //std :: cout << testArr << std :: endl;
    testArr.printArray();

    testArr.insertAtIndex(-23, 2, 3);
    //std :: cout << testArr << std :: endl;

    testArr.deleteAtIndex(2, 2);
    //std :: cout << testArr << std :: endl;

    testArr.removeAtIndex(4, 4);
    //std :: cout << testArr << std :: endl;

    testArr.extendCapacity();
    //std :: cout << testArr << std :: endl;

    testArr.shrinkCapacity();
    //std :: cout << testArr << std :: endl;

    testArr.searchAndRetrieve(rows, cols, -23);
    //std :: cout << testArr << std :: endl;

system("pause");
    return 0;
}

Arrays.h:

/*=================================================================================================
 * ==========================
    2D multifunctional arrays:
    ==========================
    Properties:
    1. Arrays are 2D on frontend but 1D linear at backend.
    2. Arrays can have different column widths for different rows.
    3. Arrays can be shirnked but auto feature in question requirement.
    4. Class requires following preoverloaded functions for non-primitive datatypes.
        4.1 Assignment operator.
        4.2 OStream operator overloaded.
        4.3 Comparison operator overloaded.
    5. Program initial feed data size is auto taken as per user created Array CAPACITY.
        5.1 User must enter N*M size input.
        5.2 Rows and Cols are user responsibility while feeding daata.
        5.3 Same rows and cols must be used when feeding data as per as while declaring capacity.
Arslaan muhammad ali
l124113
sec a ds
=================================================================================================*/
#ifndef ARRAYS_HEADER_H
#define ARRAYS_HEADER_H

#include <cstdlib>
#include <iostream>

template <class Type>
class Arrays
{
    Type *arr;
    int rows, *rowSize,
        size, cap;
    int findRowNO(int);
    int findColNO(int);
    int convertToLinearIndex(const int, const int);
    void copy(const Arrays<Type>&);
void printArray();


public:
    //constructors.
    Arrays(int, int);
    Arrays(const Arrays<Type>&);
    ~Arrays();

    //methods to perform required tasks...
    //input function to feed initial data.
    void feedInitData(int, int, Type**);

    //the function will insert a new element at given index also
    //updates the specific column size of that particular row.
    void insertAtIndex(const Type&, int, int);

    //the function will replaces a new element at given index also
    //does not update the specific column size of that particular row.
    void replaceAtIndex(const Type&, int, int);

    //the function will delete element at given index
    //array size will be decreased so it capacity.
    void deleteAtIndex(int, int);

    //the function will delete element at given index
    //capacity will remain same.
    void removeAtIndex(int, int);

    //the function will double the capacity of Arrays.
    void extendCapacity();

    //the function will half the capacity irrespective of data loss.
    void shrinkCapacity();

    //the function will search for given data and return (X,Y) if found else (-1,-1)
    void searchAndRetrieve(int&, int&, const Type&);

    //the function will retrieve any value from the given index.
    Type& retrieveAtIndex(int, int);

    //YET TO BE IMPLEMENTED CORRECTLY
    //the function will print Arrays
    //requires overloaded << for all non-primitive data types.
    //std :: ostream& operator<<(std :: ostream&);
    void printArray();

    //the function will assign one object to other.
    const Arrays<Type>& operator=(const Arrays<Type>&);
};

template <class Type>
int Arrays<Type> :: findRowNO(int index)
{
    int rowNum = 0, currRow = 0;
    while(currRow <= index)
        currRow += rowSize[rowNum++];
    return rowNum - 1;
}

template <class Type>
int Arrays<Type> :: findColNO(int index)
{
    int trows = findRowNO(index), tcols = 0;
    for(int i = 0; i <= trows; ++i)
        tcols += rowSize[i];
    tcols -= index;
    return tcols;
}

template <class Type>
int Arrays<Type> :: convertToLinearIndex(int xco, int yco)
{
    int index = 0;
    for(int i = 0; i < xco; ++i)
        index += rowSize[i];
    index += yco;
    return index;
}

template <class Type>
void Arrays<Type> :: copy(const Arrays<Type>& next)
{
    delete [] arr;
    rows = next.rows;
    for(int i = 0; i < rows; ++i)
        rowSize[i] = next.rowSize[i];
    cap = next.cap;
    size = next.size;
    arr = new Type [cap];

    for(int i = 0; i < size; ++i)
        arr[i] = next.arr[i];
    return ;
}

template <class Type>
Arrays<Type> :: Arrays(int rows2, int cols2)
{
    if(rows2 > 0 && cols2 > 0)
        rows = rows2;
    else rows = cols2 = 10;
    rowSize = new int [rows];
    for(int i = 0; i < rows; ++i)
        rowSize[i] = cols2;

    cap = rows2 * cols2;
    size = 0;
    arr = new Type [cap];
}

template <class Type>
Arrays<Type> :: Arrays(const Arrays<Type>& next)
{
    delete [] arr;
    rows = next.rows;
    for(int i = 0; i < rows; ++i)
        rowSize[i] = next.rowSize[i];
    cap = next.cap;
    size = next.size;
    arr = new Type [cap];

    for(int i = 0; i < size; ++i)
        arr[i] = next.arr[i];
}

template <class Type>
Arrays<Type> :: ~Arrays()
{
    delete [] arr;
    delete [] rowSize;
}

//input function to feed initial data.
template <class Type>
void Arrays<Type> :: feedInitData(int rows2, int cols2, Type** data)
{
    for(int i = 0; i < rows2; ++i)
        for(int j = 0; j < cols2; ++j)
            arr[i * rows2 + j] = data[i][j];
    size = (rows2 * cols2) - 1;
    return ;
}


template <class Type>
void Arrays<Type> :: insertAtIndex(const Type &next, int xpos, int ypos)
{
    //invalid index case
    int pos = convertToLinearIndex(xpos, ypos);
    if(pos > cap) return ;

    //valid index case.
    //taking care of row<=>rowSize.
    int index = findRowNO(pos);
    rowSize[index]++;

    Type *temp = new Type[cap + 1];
    for(int i = 0; i < pos; ++i)
        temp[i] = arr[i];
    temp[pos] = next;
    for(int i = pos; i < size; ++i)
        temp[i + 1] = arr[i];
    delete [] arr;

    arr = temp;
    cap++; size++;
}

template <class Type>
void Arrays<Type> :: replaceAtIndex(const Type &next, int xpos, int ypos)
{
    //invalid index case.
    int pos = convertToLinearIndex(xpos, ypos);
    if(pos > cap) return ;

    //replaces value at position pos or (xco, yco).
    arr[pos] = next;
    return ;
}

//removes an element from index.
template <class Type>
void Arrays<Type> :: deleteAtIndex(int xpos, int ypos)
{
    //invalid index case.
    int pos = convertToLinearIndex(xpos, ypos);
    if(pos > cap) return ;

    //valid index case.
    //taking care of row<=>rowSize.
    int index = findRowNO(pos);
    rowSize[index]--;

    Type *temp = new Type[cap - 1];
    for(int i = 0; i < pos; ++i)
        temp[i] = arr[i];
    for(int i = pos; i < size; ++i)
        temp[i] = arr[i + 1];
    delete [] arr;

    arr = temp;
    cap--; size--;
}

//removes an element from index but does not remove space.
template <class Type>
void Arrays<Type> :: removeAtIndex(int xpos, int ypos)
{
    //invalid index case.
    int pos = convertToLinearIndex(xpos, ypos);
    if(pos > cap) return ;

    for(int i = pos + 1; i < size; ++i)
        arr[i - 1] = arr[i];
    size--;
}

//double capacity.
template <class Type>
void Arrays<Type> :: extendCapacity()
{
    cap += rows * rows;
    int prevRows = rows; rows *= 2;
    Type *temp1 = new Type[cap];
    int *temp2 = new Type[rows];

    for(int i = 0; i < size; ++i)
        temp1[i] = arr[i];

    for(int i = 0; i < prevRows; ++i)
        temp2[i] = rowSize[i];

    for(int i = prevRows; i < rows; ++i)
        temp2[i] = prevRows;

    delete [] arr; delete [] rowSize;
    arr = temp1; rowSize = temp2;
}

//half capacity.
template <class Type>
void Arrays<Type> :: shrinkCapacity()
{
    if(size >= cap / 2)
        size = cap / 2 - 1;

    rows /= 2; cap = 0;
    for(int i = 0; i < rows; ++i)
        cap += rowSize[i];

    Type *temp1 = new Type [cap];
    int *temp2 = new int [rows];

    for(int i = 0; i < cap; ++i)
        temp1[i] = arr[i];

    for(int i = 0; i < rows; ++i)
        temp2[i] = rowSize[i];

    delete [] arr; delete [] rowSize;
    arr = temp1; rowSize = temp2;
}

//returns (-1,-1) if not found else (X,Y) values.
template <class Type>
void Arrays<Type> :: searchAndRetrieve(int &row, int &col, const Type& find)
{
    int index = -1;
    for(int i = 0; i < size; ++i)
        if(find == arr[i]) {
            index = i;
            break;
        }
    if(index == -1)
        row = col = -1;
    else {
        row = findRowNO(index);
        col = findColNO(index);
    }
}

//the function will retrieve any value from the given index.
template <class Type>
Type& Arrays<Type> :: retrieveAtIndex(int xco, int yco)
{   return arr[convertToLinearIndex(xco, yco)]; }

template <class Type>
void Arrays<Type> :: printArray()
{
    for(int i = 0; i < rows; ++i)
    {
        for(int j = 0; j < rowSize[i]; ++j)
            std :: cout << arr[convertToLinearIndex(i, j)] << ' ';
        std :: cout << std :: endl;
    }
    return ;
}

//YET TO BE IMPLEMENTED CORRECTLY.
/*template <class Type>
std :: ostream& Arrays<Type> :: operator<<(std :: ostream& out)
{
    for(int i = 0; i < rows; ++i)
        for(int j = 0; j < rowSize[i]; ++j)
            out << arr[i] << ' ';
        out << '\n';
    return out;
}*/

template <class Type>
const Arrays<Type>& Arrays<Type> :: operator=(const Arrays<Type>& right)
{
    //avoiding self-copying.
    if(this != &right)
        copy(right);
    return *this;
}

#endif


Comments

Popular Posts