-1

I have a homework assignment asking me to implement a matrix class with that uses dynamic allocation to store its elements. The class should allow the addition and substraction. It needs to free memory that it no longer needs to store elements.

My idea was to create two classes: matrix class and element class. The element class has two properties (a key and the address to the next element). The proble is, should I store all the elements in the matrix class somehow or only an address to the first element, and make all the operation based on that first element? What do you think of my approach?

CashCow
  • 30,981
  • 5
  • 61
  • 92
johnjhye
  • 15
  • 2
  • 6
  • It looks like you are confusing between matrix and linked list... Matrix element should not know anything about another elements. – Alex F Nov 12 '13 at 10:50
  • YOu don't need element class. And you don't need address of the next element. – SigTerm Nov 12 '13 at 10:51
  • Is the size known at compile time or determined at runtime (dynamic allocation can be done with both; mandatory for one)? And is the intent for a compressed *sparse* matrix ? By the instructions, it appears so, in which case a whole lotta pointer management is about to come your way. If you choose the approach you're taking, you're going to need additional node types, but its feasible none-the-less. – WhozCraig Nov 12 '13 at 10:52
  • @AlexFarber as I know, an array can be implemented as a list, if you want to take full control of the # of elements. – johnjhye Nov 12 '13 at 10:55
  • @WhozCraig not really specified but it asks me to determine the size later. Kinda weird since it should be a square matrix. Nothing on sparse matrix either. – johnjhye Nov 12 '13 at 10:56
  • this is basically asking for a [sparse matrix](http://en.wikipedia.org/wiki/Sparse_matrix) class. It may not say so explicitly, but the implementation should be similar. – Shep Nov 12 '13 at 10:59
  • When you say "elements created dynamically" you actually mean your matrix is responsible for dynamically allocating the elements, not that it creates elements that are dynamically created (with new) that your matrix must clean up. If you mean something, say it. – CashCow Nov 12 '13 at 11:50

3 Answers3

0

Perhaps if you say what you mean you wouldn't get people answering what you wrote.

Your matrix needs to dynamically allocate to store its members.

The best way to do this is not to be two-dimensional but to be single-dimensional in its allocation. You need M * N elements so allocate M*N in one go.

To find element( i, j ), it is actually element ( i * M ) + j.

Thus you have something like, if the elements are double

class Matrix
{
private:
     double * m_mem;
     size_t m_width;
     size_t m_height;
public:
     Matrix( size_t width, size_t height );
     ~Matrix();

     double operator()( size_t i, size_t j ) const
     {
         return m_mem[ i * m_width + j ];
     }
     double& operator()( size_t i, size_t j ) 
     {
         return m_mem[ i * m_width + j ];
     }

     size_t width() const
     {
         return m_width;
     }

     size_t height() const
     {
         return m_height;
     }

     Matrix(Matrix const& other ); // you implement
     Matrix& operator=( Matrix const& other ); // you implement
};
  • You will want 2 overloads for operator(), a non-const one for setting these members.
  • You might wish to bounds check.

Allocate thus:

     Matrix::Matrix( size_t width, size_t height ) :
        m_mem( new double[width * height] ),
        m_width( width ),
        m_height( height )
     {
     }

Free thus:

     Matrix::~Matrix()
     {
           delete [] m_mem;
     }

You will need to manage the copying and assigning, given the rule of 3.

It is not possible to deallocate part of your matrix.

If you want to make the Matrix generic, you must write a template. But I don't know if you have yet learnt how to write templates.

For addition and subtraction, you could use class members or:

     Matrix operator+( Matrix const& left, Matrix const& right )
     {
         assert( left.width == right.width );
         assert( left.height == right.height );
         Matrix sum( left.width, left.height );
         for( size_t i = 0; i < left.width; ++i )
         {
             for( size_t j = 0; j < left.height; ++j )
             {
                 sum( i, j ) = left( i, j ) + right( i, j );
             }
         }
         return sum; // in C++11 return std::move(sum) and return-type Matrix&&
     }

If you used class members (or make the operator a friend) you can make use of your internal structure by running through every element in the one-dimensional arrays in a single (rather than nested) loop. It won't improve the complexity of the algorithm which is still height * width, although it may be a tiny bit faster due to the pointer arithmetic.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • No. Sum of matrix A + B means C[0][0] = A[0][0]+B[0][0] Sorry if I didn't make that clear. – johnjhye Nov 12 '13 at 10:57
  • 1
    Writing your question in a very unclear way is no reason to start downvoting answers. Your question is a homework one and I am not going to help you anymore, in fact I will downvote your question AND vote to close it. – CashCow Nov 12 '13 at 11:46
  • Your sum of matrix is what it makes sense to mean, but you said "Matrix of dynamically allocated elements" which that is not. – CashCow Nov 12 '13 at 12:07
  • Thank you and again, I'm sorry for the confusion. Apparently I can't even vote on answers so that's not me downvoting you. Thanks again! – johnjhye Nov 12 '13 at 13:19
  • I retracted the downvote and close too because your second paragraph shows that you have had some thought in the design model of your answer, and therefore you have not simply asked "show me the codez". – CashCow Nov 12 '13 at 14:29
  • You don't need nested loop for operator+. Just access internal arrays directly and walk through elements, adding them. Also you could store elements in std::vector instead of allocating them. – SigTerm Nov 13 '13 at 12:21
  • I just use boost::numeric::ublas::matrix and don't write my own. The OP said he had to use allocation, not vector. Obviously if I didn't have boost and had to write it myself I would use vector or some other library way. – CashCow Nov 14 '13 at 17:18
0

You don't need "element class". You don't need "address of the next element". IMO, you're making this needlessly complicated.

A matrix is a 2D array.
A simplest way to represent 2D array with numRows rows and numColumns columns is to make 1D array with size numRows * numColumns.
In such array offset of individual element (rowIndex, columnIndex) can be calculated as rowIndex * numCOlumns + columnIndex, where both indexes are zero-based. And you do know how to allocate 1D array, right?

SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • Ok, I understand you're saying. Now for the implementation, I simply have the matrix class constructed based on a certain # of elements that is given. I think I'll use this. Thanks! – johnjhye Nov 12 '13 at 11:21
0
Class Matrix:
{
private:
int**m;
public:
Matrix();//allocate memory
Realocate_memory(int**, int rows, int cols); //in case you want to modify the size of the matrix - this will be the most complicated part as you need to handle memory allocation.
Free(int**m, int rows, int cols);

// other methods....
}

the tricky part here is deleting the not used elements- since you you have to keep the matrix structure there are a few constraints: - you can only delete entire rows/columns - you may move data around is that is allowed so that you end up with full rows/cols of unused elements - but personally I wouldn't bother with this approach

You can also allocate more memory when you run out of space - here you can take the Dynamic array approach: - allocate a new matrix 2x size - copy the old one in the new one - free the old one.

hope this helps!

Pandrei
  • 4,843
  • 3
  • 27
  • 44