C++/Fundamentals of Data Structures in C++(Horowitz)

C++ Fundamentals of Data Structures(C++ 자료구조론) 2.4 연습문제

꾸준함. 2017. 7. 29. 16:31

[Exercises 1]

/*

How much time does it take to locate an arbitrary element A[i][j] in the representation of this section and to change its value

이번 섹션에서 나타낸 이차행렬의 임의 원소인 A[i][j]를 찾고 값을 변경하는데 걸리는 시간은?

*/

일반적인 방법을 쓸 경우 : O(rows*cols)

FastTranspose를 쓸 경우 : O(cols + terms)

[Exercises 2]

/*

Analyze carefully the computing time and storage requirements of function FastTranspose

FastTranspose 함수의 작동시간과 저장 크기 조건을 분석해라

 

O(terms+cols)

*/

#include <iostream>

using namespace std;

 

class SparseMatrix;

 

class MatrixTerm

{

        friend class SparseMatrix;

private:

        int row, col, value;

};

 

class SparseMatrix

{

private:

        int rows, cols, terms, capacity;

        MatrixTerm *smArray;

public:

        SparseMatrix(int MaxRow, int MaxCol, int term)

        {

               rows = MaxRow;

               cols = MaxCol;

               terms = term;

               capacity = 0;

        }

        SparseMatrix FastTranspose()

        {

               //Return the transpose of *This in O(terms+cols) time

               SparseMatrix b(cols, rows, terms);

               if (terms > 0)

               {

                       //nonzero matrix, 0이 아닌 행렬

                       int *rowSize = new int[cols];

                       int *rowStart = new int[cols];

                       //compute rowSize[i]=number of terms in row i of b

                       //RowSize[i]=b의 행 i에 들어갈 항의 수를 계산

                       fill(rowSize, rowSize + cols, 0); //초기화

                       for (int i = 0; i < terms; i++)

                              rowSize[smArray[i].col]++;

 

                       //rowStart[i]=starting position of b

                       //rowStart[i]b의 행 i의 시작 지점

                       rowStart[0] = 0;

                       for (int i = 1; i < cols; i++)

                              rowStart[i] = rowStart[i - 1] + rowSize[i - 1];

 

                       for (int i = 0; i < terms; i++)

                       {

                              //copy from *this to b

                              //b로 복사

                              int j = rowStart[smArray[i].col];

                              b.smArray[j].row = smArray[i].col;

                              b.smArray[j].col = smArray[i].row;

                              b.smArray[j].value = smArray[i].value;

                              rowStart[smArray[i].col]++;

                       }

                       delete[]rowSize;

                       delete[]rowStart;

               }

               return b;

        }

};

[Exercises 3]

/*

Write C++ functions to input and output a sparse matrix.

sparse matrix를 입출력하는 C++ 함수를 작성한다.

These should be implemented by overloading the >> and << operators

이를 위해 >> << 연산자가 오버로딩되어야한다.

You should design the input and output formats.

입출력 형식은 본인이 직접 디자인한다.

However, the internal representation should be a one dimensional array of nonzero terms as used in this section.

하지만, 이번 섹션에서 표현했듯이 희소행렬은 일차원 배열로 표현되어야한다.

*/

#include <iostream>

using namespace std;

 

class SparseMatrix;

 

class MatrixTerm

{

        friend class SparseMatrix;

        friend ostream &operator<<(ostream &os, const SparseMatrix S); //출력

        friend istream &operator>>(istream &is, SparseMatrix S); //입력

private:

        int row, col, value;

};

 

class SparseMatrix

{

private:

        int rows, cols, terms, capacity;

        MatrixTerm *smArray;

public:

        SparseMatrix(int MaxRow = 1, int MaxCol = 1, int term = 0)

        {

               rows = MaxRow;

               cols = MaxCol;

               terms = term;

               if (term > 0)

                       capacity = term;

               else

                       capacity = 1;

               smArray = new MatrixTerm[capacity];

        }

        SparseMatrix FastTranspose()

        {

               //Return the transpose of *This in O(terms+cols) time

               SparseMatrix b(cols, rows, terms);

               if (terms > 0)

               {

                       //nonzero matrix, 0이 아닌 행렬

                       int *rowSize = new int[cols];

                       int *rowStart = new int[cols];

                       //compute rowSize[i]=number of terms in row i of b

                       //RowSize[i]=b의 행 i에 들어갈 항의 수를 계산

                       fill(rowSize, rowSize + cols, 0); //초기화

                       for (int i = 0; i < terms; i++)

                              rowSize[smArray[i].col]++;

 

                       //rowStart[i]=starting position of b

                       //rowStart[i]b의 행 i의 시작 지점

                       rowStart[0] = 0;

                       for (int i = 1; i < cols; i++)

                              rowStart[i] = rowStart[i - 1] + rowSize[i - 1];

 

                       for (int i = 0; i < terms; i++)

                       {

                              //copy from *this to b

                              //b로 복사

                              int j = rowStart[smArray[i].col];

                              b.smArray[j].row = smArray[i].col;

                              b.smArray[j].col = smArray[i].row;

                              b.smArray[j].value = smArray[i].value;

                              rowStart[smArray[i].col]++;

                       }

                       delete[]rowSize;

                       delete[]rowStart;

               }

               return b;

        }

        friend ostream &operator<<(ostream &os, const SparseMatrix S); //출력

        friend istream &operator>>(istream &is, SparseMatrix S); //입력

};

 

ostream &operator<<(ostream &os, const SparseMatrix S)

{

        os << ": " << S.rows << " : " << S.cols << endl;

        os << "0이 아닌 요소의 수: " << S.terms << endl;

 

        for (int i = 0; i < S.terms; i++)

        {

               os << "(" << S.smArray[i].row << ", " << S.smArray[i].col << ", " << S.smArray[i].value << ")" << endl;

        }

        return os;

}

 

istream &operator>>(istream &is, SparseMatrix S)

{

        cout << ", , 그리고 0이 아닌 요소의 수 입력: ";

        cin >> S.rows >> S.cols >> S.terms;

        if (S.terms > S.capacity)

        {

               cout << "범위를 초과했습니다";

               exit(1);

        }

 

        for (int i = 0; i < S.terms; i++)

        {

               cout << i + 1 << "-> , , 그리고 값 입력: " << endl;

               is >> S.smArray[i].row >> S.smArray[i].col >> S.smArray[i].value;

        }

        return is;

}

[Exercises 5]

/*

Develop a corrctness proof for function Multiply(Program 2.14)

희소행렬 곱셈 함수의 정확성을 증명해라?

 

질문의 의도를 모르기 때문에 우선 곱셈 함수만 작성하겠습니다

*/

#include <iostream>

using namespace std;

 

class SparseMatrix;

 

class MatrixTerm

{

        friend class SparseMatrix;

        friend ostream &operator<<(ostream &os, const SparseMatrix S); //출력

        friend istream &operator>>(istream &is, SparseMatrix S); //입력

private:

        int row, col, value;

};

 

class SparseMatrix

{

private:

        int rows, cols, terms, capacity;

        MatrixTerm *smArray;

public:

        SparseMatrix(int MaxRow=1, int MaxCol=1, int term=0)

        {

               rows = MaxRow;

               cols = MaxCol;

               terms = term;

               if (term > 0)

                       capacity = term;

               else

                       capacity = 1;

               smArray = new MatrixTerm[capacity];

        }

        SparseMatrix FastTranspose()

        {

               //Return the transpose of *This in O(terms+cols) time

               SparseMatrix b(cols, rows, terms);

               if (terms > 0)

               {

                       //nonzero matrix, 0이 아닌 행렬

                       int *rowSize = new int[cols];

                       int *rowStart = new int[cols];

                       //compute rowSize[i]=number of terms in row i of b

                       //RowSize[i]=b의 행 i에 들어갈 항의 수를 계산

                       fill(rowSize, rowSize + cols, 0); //초기화

                       for (int i = 0; i < terms; i++)

                              rowSize[smArray[i].col]++;

 

                       //rowStart[i]=starting position of b

                       //rowStart[i] b의 행 i의 시작 지점

                       rowStart[0] = 0;

                       for (int i = 1; i < cols; i++)

                              rowStart[i] = rowStart[i - 1] + rowSize[i - 1];

 

                       for (int i = 0; i < terms; i++)

                       {

                              //copy from *this to b

                              //b로 복사

                              int j = rowStart[smArray[i].col];

                              b.smArray[j].row = smArray[i].col;

                              b.smArray[j].col = smArray[i].row;

                              b.smArray[j].value = smArray[i].value;

                              rowStart[smArray[i].col]++;

                       }

                       delete[]rowSize;

                       delete[]rowStart;

               }

               return b;

        }

        void ChangeSize1D(const int newSize)

        {

               MatrixTerm *temp = new MatrixTerm[newSize];

               copy(smArray, smArray + terms, temp);

               delete[] smArray;

               smArray = temp;

        }

        void StoreSum(const int v, const int r, const int c)

        {

               if (v != 0)

               {

                       if (terms == capacity)

                              ChangeSize1D(2 * capacity);

                       smArray[terms].row = r;

                       smArray[terms].col = c;

                       smArray[terms++].value = v;

               }

        }

        SparseMatrix Multiply(SparseMatrix b)

        {

               if (cols != b.rows)

                       throw "Incompatible matrices";

               SparseMatrix bXpose = b.FastTranspose();

               SparseMatrix d(rows, b.cols, 0);

               int currRowIndex = 0, currRowBegin = 0, currRowA = smArray[0].row;

               //set boundary conditions

               if (terms == capacity)

                       ChangeSize1D(terms + 1);

               bXpose.ChangeSize1D(bXpose.terms + 1);

               smArray[terms].row = rows;

               bXpose.smArray[b.terms].row = b.cols;

               bXpose.smArray[b.terms].col = -1;

               int sum = 0;

               while (currRowIndex < terms)

               {

                       int currColB = bXpose.smArray[0].row;

                       int currColIndex = 0;

                       while (currColIndex <= b.terms)

                       {

                              if (smArray[currRowIndex].row != currRowA)

                              {

                                      d.StoreSum(sum, currRowA, currColB);

                                      sum = 0;

                                      currRowIndex = currRowBegin;

                                      while (bXpose.smArray[currColIndex].row == currColB)

                                              currColIndex++;

                                      currColB = bXpose.smArray[currColIndex].row;

                              }

                              else if (bXpose.smArray[currColIndex].row != currColB)

                              {

                                      d.StoreSum(sum, currRowA, currColB);

                                      sum = 0;

                                      currRowIndex = currRowBegin;

                                      currColB = bXpose.smArray[currColIndex].row;

                              }

                              else

                              {

                                      if (smArray[currRowIndex].col < bXpose.smArray[currColIndex].col)

                                              currRowIndex++;

                                      else if (smArray[currRowIndex].col == bXpose.smArray[currColIndex].col)

                                      {

                                              sum += smArray[currRowIndex].value*bXpose.smArray[currColIndex].value;

                                              currRowIndex++;

                                              currColIndex++;

                                      }

                                      else

                                              currColIndex++;

                              }

                       }

                       while (smArray[currRowIndex].row == currRowA)

                              currRowIndex++;

                       currRowBegin = currRowIndex;

                       currRowA = smArray[currRowIndex].row;

               }

               return d;

        }

        friend ostream &operator<<(ostream &os, const SparseMatrix S); //출력

        friend istream &operator>>(istream &is, SparseMatrix S); //입력

};

 

ostream &operator<<(ostream &os, const SparseMatrix S)

{

        os << ": " << S.rows << " : " << S.cols << endl;

        os << "0이 아닌 요소의 수: " << S.terms << endl;

 

        for (int i = 0; i < S.terms; i++)

        {

               os << "(" << S.smArray[i].row << ", " << S.smArray[i].col << ", " << S.smArray[i].value << ")" << endl;

        }

        return os;

}

 

istream &operator>>(istream &is, SparseMatrix S)

{

        for (int i = 0; i < S.terms; i++)

        {

               cout << i + 1 << "-> , , 그리고 값 입력: " << endl;

               is >> S.smArray[i].row >> S.smArray[i].col >> S.smArray[i].value;

        }

        return is;

}

 

int main(void)

{

        SparseMatrix s(3, 3, 3), t(3, 3, 3);

        cout << "s 행렬 입력"<<endl;

        cin >> s;

        cout << "s 희소행렬" << endl << s << endl;

        cout << "t 행렬 입력" << endl;

        cin >> t;

        cout << "t 희소행렬" << endl << t << endl;

        SparseMatrix mul = s.Multiply(t);

        cout << "s*t 희소행렬" << endl << mul << endl;

        return 0;

}


[참고] Fundamentals of Data Structures in C++(Horowitz, Sahni, Mehta) 원서,


*영어로 적혀있는 문제를 제가 의역한 것이기 때문에 오역이 있을 수 있습니다. 양해 부탁드립니다.

*4, 6, 7번 문제는 생략하였습니다.


*벌써부터 어려워진 듯한 느낌입니다... 문제를 푸는데 몇시간씩이나 걸리다니...

반응형