[C++] 2차원 벡터.

assasasa의 이미지

2차원 데이터를 표현하는 벡터를 만들고자 합니다.

#include <iostream>
#include <vector>

using std::vector;
typedef vector< vector<int> > Matrix ;
int main(){

	vector<int> row1 ;
	row1.push_back(1);
	row1.push_back(2);
	row1.push_back(3);
	row1.push_back(4);
	
	vector<int> row2 ;
	row2.push_back(11);
	row2.push_back(12);
	row2.push_back(13);
	row2.push_back(14);

	vector< vector<int> > matrix;
	matrix.push_back( row1 );
	matrix.push_back( row2 );

	for( int i=0 ; i < 2 ; ++i){
		for( int j=0  ; j < 4 ; ++j){
			std::cout<<"("<<i<<","<<j<<") "<< (matrix[i][j]) <<" " ; 
		}
		std::cout<<std::endl;	
	}


	return 0;
}

결과는

(0,0) 1 (0,1) 2 (0,2) 3 (0,3) 4
(1,0) 11 (1,1) 12 (1,2) 13 (1,3) 14

와 같이 나옵니다만. 행의 갯수를 모르는 상황에서는
위와 같이 row1,2,..이렇게는 사용하지 못할거 같습니다.
물론 row1,2,의 열의 갯수를 맞추어 주는 장치가 없는 것도 문제입니다.
이건 논외로 치고(잘 아시는 분 있으면..코멘트 부탁.).

제가 알고싶은것은

vector< vector<int> > Matrix ;

라고 정의했다면, 데이터를 어떻게 넣어야 하는지요?
Matrix[0][0].push_back(1) 은 당연히 안 될테고. 음...
고민중입니다.
tinywolf의 이미지

흐음.. 상당히 헷갈리는데요..
2차원으로 활용하려면 무언가 다른 수를 써야할 것같습니다..

ㅡ_ㅡ;

danskesb의 이미지

저의 경우는 row 벡터를 따로 만들어 준 다음에, 새 열을 넣을 때마다 지우고 새로 쓰는 방법을 사용합니다.

체스맨의 이미지

논외의 답변이지만, 코드상의 vector, matrix 가 수학적인 vector, matrix 라면
경험상 그냥 단순히 배열을 쓰는게 가장 좋은 것 같습니다.
간단하고 다른 수학 라이브러리들과 호환성도 좋고, 몇바이트나마
메모리도 더 적게 듭니다.

Orion Project : http://orionids.org

doldori의 이미지

이렇게 하는 방법은 있습니다.

typedef vector<int> Row;
typedef vector<Row> Matrix;

Matrix matrix; 

matrix.push_back(Row());            // push back an empty vector
Row* row = &matrix.back();  // pointer to the last row
row->push_back(1); 
row->push_back(2); 
row->push_back(3); 
row->push_back(4); 

matrix.push_back(Row());
row = &matrix.back();
row->push_back(11); 
row->push_back(12); 
row->push_back(13); 
row->push_back(14); 

for (Matrix::size_type i = 0; i != matrix.size(); ++i)
{
    for (Row::size_type j = 0; j != matrix[i].size(); ++j)
        std::cout<<"("<<i<<","<<j<<") "<< (matrix[i][j]) <<" " ; 
    std::cout<<std::endl;    
} 

또한 r by c의 배열처럼 만드려면
Matrix m(r, Row(c));
// use m[0][0] through m[r-1][c-1]

그것도 아니면 Boost.MultiArray를 쓰는 방법도 있고요.
doldori의 이미지

체스맨 wrote:
논외의 답변이지만, 코드상의 vector, matrix 가 수학적인 vector, matrix 라면
경험상 그냥 단순히 배열을 쓰는게 가장 좋은 것 같습니다.
간단하고 다른 수학 라이브러리들과 호환성도 좋고, 몇바이트나마
메모리도 더 적게 듭니다.

그런데 C++에서는 가변길이 배열을 쓸 수 없으니 배열로 일반적인 행렬을 구현하기는
상당히 까다롭죠. (적어도 귀찮기는 합니다.) 함수 인자로 넘길 때도 그렇고요.
assasasa의 이미지

Matrix m(r, Row(c));
// use m[0][0] through m[r-1][c-1]

위의 초기화 코드가 상당히 메리트가 있군요. c개의 컬럼을
가진, 벡터를 r 개 넣어라~라는 뜻이죠?
감사 감사.

어쨋든 Matrix의 push_back 을 할경우, 그 인자가 vector형이
와야 하기 때문에 빈 row를 입력하여야 된다는 이야기시죠?

"마무리가 반이다" -- woox

쌀밥의 이미지

assasasa wrote:
2차원 데이터를 표현하는 벡터를 만들고자 합니다.
제가 알고싶은것은
vector< vector<int> > Matrix ;

라고 정의했다면, 데이터를 어떻게 넣어야 하는지요?
Matrix[0][0].push_back(1) 은 당연히 안 될테고. 음...
고민중입니다.

만약 4 by 3의 행렬을 원하신다면
Matrix.resize(4);
Matrix[0].resize(3);
Matrix[1].resize(3);
Matrix[2].resize(3);
Matrix[3].resize(3);
이라고 선언을 해서 공간을 먼저 확보하시고
Matrix[0][0] = 1;
이렇게 사용하시면 될듯합니다.

하지만 제 생각에는 이런식의 2차원 벡터보다는
vector< int > Matrix;
Matrix.resize( 4*3 );
Matrix[ i * 4 + j ] 의 형태로 사용하시는게 좋아 보입니다.
실제 C 에서 2차원 배열도 이런식으로 동작하는 거구요...

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

익명 사용자의 이미지

정확한 답변은 아니지만
More Effective C++이란 책에 C++에서 2차원 벡터를 만드는 방법이 있습니다.
제가 지금 책이 없어서... 자세한 내용은 ㅠㅠ;

쌀밥의 이미지

오늘 C# 책을 보다가 이런 종류의 벡터 사용을 jagged array (톱니형 배열) 라고 한다는 것을 알게 되었습니다.

나름대로 유용하게 쓸 수 있는 사용방법이겠지만
질문 올리신 분의 의도는

Quote:
열의 갯수를 맞추어 주는 장치가 없는 것도 문제입니다.
로 봐서...
C에서와 같은 형태로 사용하는 것이니
아래와 같이 사용하는 것이 적당해 보입니다.
int& MyAt( vector<int>& vec, int row, int col, int maxCol)
{
    return vec.at(row * maxCol + col);
}

vector< int > Matrix( 4*3 );
MyAt(Matrix, i, j, 4) = 300;
printf("%d\n", MyAt(Matrix, i, j, 4) ); 

그대로 사용할 수는 없겠지만.. 참고하세요...

*PS:왠지 저렇게 써 놓고보니 template으로 만들고 싶은 충동도 들지만;;

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

blna999의 이미지

제 경우에는 아래의 코드를 이용해서 vector로 2차원 matrix을 만들었습니다.

typedef vector< vector<float> > float_matrix;
float_matrix mat;
shrinkMatrix(mat);
for (i=0; i<row; i++) {
  mat.push_back(*(new vector<float>));
  mat[i].reserve(col);
}

shrinkMatrix (float_matrix& m) {
  float_matrix::iterator pos;
  for (pos=m.begin(); pos!=m.end(); ++pos) pos->clear();
  m.clear();
  float_matrix(m).swap(m);
}

앞의 분들과 차이점이 있다면 float_matrix를 선언한 다음에 바로 shrink시켜서 row의 수를 제한한 점과 reserve를 이용해서 col만큼의 메모리를 확보한 점이 다른 것 같습니다.
doldori의 이미지

blna999 wrote:
제 경우에는 아래의 코드를 이용해서 vector로 2차원 matrix을 만들었습니다.

좀 이해하기 힘든 코드입니다.
typedef vector< vector<float> > float_matrix;
float_matrix mat;
shrinkMatrix(mat);
for (i=0; i<row; i++) {
  mat.push_back(*(new vector<float>));
  mat[i].reserve(col);
}

new를 했으면 나중에 해제를 해야 할 텐데 어떻게 하시는지요?
따로 포인터를 저장해 두거나 auto_ptr을 써야만 가능할 것 같은데...
mat.push_back(vector<float>())으로 충분하지 않나요?
그리고 reserve()를 쓰면 나중에 push_back()을 해야 한다는 점도 좀 불편해 보이고요.
재할당을 막을 목적이면 resize()가 더 편할 듯 싶은데요.
  float_matrix(m).swap(m);

m을 복사한 임시 matrix를 m과 바꾼다... -.-a
이런 목적이면 shrink_matrix() 대신 float_matrix().swap(m) 로 충분해 보입니다만.
그보다 float_matrix를 선언한 직후에는 어차피 빈 vector일 것이니 이런 작업 자체가
필요 없겠는데요.
doldori의 이미지

그리고 TC++PL 22장에 std::valarray를 이용해서 효율적으로 2차원 행렬을
구현한 예가 있으니 참고하십시오.

blna999의 이미지

for (i=0; i<row; i++) {
  mat.push_back(*(new vector<float>));
  mat[i].reserve(col);
}

이 부분은 확실히 아래처럼 고치는 것이 좋을 것 같군요. 고맙습니다~^^
for (i=0; i<row; i++) {
  mat.push_back(vector<float>());
  mat[i].resize(col);
}

doldori wrote:
이런 목적이면 shrink_matrix() 대신 float_matrix().swap(m) 로 충분해 보입니다만.

shrink_matrix()는 matrix를 다른 크기로 재사용하기 위한 목적도 가지고 작성했었습니다. 재사용할 때는 마찬가지로 shrink_matrix()를 호출하고 row와 col을 재설정했는데 이부분도 좀 더 편리한 방법이 있을까요?
doldori의 이미지

blna999 wrote:
shrink_matrix()는 matrix를 다른 크기로 재사용하기 위한 목적도 가지고 작성했었습니다. 재사용할 때는 마찬가지로 shrink_matrix()를 호출하고 row와 col을 재설정했는데 이부분도 좀 더 편리한 방법이 있을까요?

위에서 보인 것과 비슷한데 row by col의 행렬을 바로 대입하면 됩니다.
어차피 대입 연산자 내에서 shrink_matrix가 하는 작업도 같이 하니까요.
이름이 길어서 번거로우니 적당히 typedef 해서 쓰면 되겠고요.
mat = vector<vector<float> >(row, vector<float>(col));
blna999의 이미지

mat = vector<vector<float> >(row, vector<float>(col)); 위에서도 있었던 얘기지만 이 코드가 정말 깔끔해 보이는군요. :D 진작에 이렇게 코딩했으면 좋았을텐데... 시간봐서 프로그램을 고쳐봐야겠네요. 코멘트해 주셔서 감사합니다~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.