1 / 61

자료구조

자료구조. 제 2 장 배열. 2.1 추상 데이타 타입과 C++ 클래스. 2.1 추상 데이타 타입과 C++ 클래스. ▶ C++ 클래스 개요 - C++ 은 클래스 기법을 사용하여 ADT 를 표현 - C++ 클래스의 구성 (1) 클래스 이름 : ( 예 : Rectangle) (2) 데이타 멤버 : 데이타 ( 예 : x1, y1, h, w) (3) 멤버 함수 : 연산의 집합 ( 예 : GetHeight(), GetWidth()). 2.1 추상 데이타 타입과 C++ 클래스.

callie
Download Presentation

자료구조

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 자료구조 제 2 장 배열

  2. 2.1 추상 데이타 타입과 C++ 클래스

  3. 2.1 추상 데이타 타입과 C++ 클래스 • ▶ C++ 클래스 개요 • - C++은 클래스 기법을 사용하여 ADT를 표현 • - C++ 클래스의 구성 • (1) 클래스 이름: (예: Rectangle) • (2) 데이타 멤버: 데이타 (예: x1, y1, h, w) • (3) 멤버 함수: 연산의 집합 • (예: GetHeight(), GetWidth())

  4. 2.1 추상 데이타 타입과 C++ 클래스 • (4) 프로그램 접근 레벨: 멤버 및 멤버함수 • 공용(public), 보호(protected), 전용(private) • public: 프로그램 어디에서도 접근 • private: 같은 클래스내, friend로 선언된 함수나 클래스 에 의해 접근 • protected: 같은 클래스내, 서브클래스, friend에 • 의해서만 접근

  5. 2.1 추상 데이타 타입과 C++ 클래스 • ----------------------------------- • #ifndefRECTANGLE_H • #define RECTANGLE_H • // Rectangle.h헤더 화일속에 • classRectangle { • public: // 다음 멤버들은 public이다. • // 다음 4개의 멤버들은 멤버 함수들이다. • Rectangle(); // 생성자 • ~Rectangle(); // 파괴자 • intGetHeight(); // 사각형의 높이를 제공 • intGetWidth(); // 사각형의 길이를 제공 • private: // 다음 멤버들은 전용이다. • // 다음 4개의 멤버들은 데이타 멤버들이다. • intx1, y1, h, w; • // (x1, y1)은 사각형의 왼쪽 하단 모서리 좌표이다. • // w는 사각형의 길이이고, h는 높이이다. • }; • #endif • ----------------------------------- • 프로그램 2.1 Rectangle 클래스의 C++ 정의

  6. 2.1 추상 데이타 타입과 C++ 클래스 • ▶ C++에서의 데이타 추상화와 캡슐화 • - 데이타 멤버: • . private(전용) 또는 protected(보호)로 선언 • -> 데이타 캡슐화 • - 멤버 함수: • .외부에서 기동될 것: public으로 선언 • .나머지: private나 protected로 선언 • (다른 멤버 함수에서 호출) • - 클래스 연산의 명세와 구현의 분리 • . 명세 부분에서 함수 프로토타입(함수 이름, • 인자 타입, 결과 타입) 정의 • -> 헤더 화일에 저장 • (예) Rectangle.h화일(프로그램 2.1의 내용) • . 함수의 기능 기술: 주석(comment)을 이용 • . 함수의 구현: 같은 이름의 소스 화일에 저장 • (예) Rectangle.C화일(프로그램 2.2의 내용) • note: 멤버 함수의 구현을 클래스 정의내에 • 포함시킬 수도 있음 • -> 인라인(inline) 함수로 취급 • int GetHeight() { return h };

  7. 2.1 추상 데이타 타입과 C++ 클래스 • ---------------------------------------- • // 소스 화일 Rectangle.C속에 • #include "Rectangle.h" • // 접두어로 사용되는 “Rectangle::"은 • // GetHeight()와 GetWidth()가 • // 클래스 Rectangle의 멤버 함수라는 것을 명시 한다. • // 이 접두어가 필요한 이유는 멤버 함수들이 • // 클래스 정의 밖에서 구현되기 때문이다 • int Rectangle::GetHeight() { return h }; • int Rectangle::GetWidth() { return w}; • ---------------------------------------- • 프로그램 2.2 Rectangle에 대한 연산의 구현

  8. 2.1 추상 데이타 타입과 C++ 클래스 • ▶ 클래스 객체의 선언과 멤버 함수의 기동 • - 클래스 객체: 변수와 똑같이 선언되고 생성됨 • - 한 객체의 멤버: 점(.), 화살표(->)로 접근 • ----------------------------------- • // 소스 화일 main.C속에 • #include <iostream.h> • #include "Rectangle.h" • main(){ • Rectangle r, s; • // r과 s는 클래스 Rectangle의 객체들이다. • Rectangle *t = &s; • // t는 클래스 객체 s에 대한 포인터이다. • ... (r, s의 값을 입력함) • // 클래스 객체의 멤버를 직접 접근하기 위해서는 • // 점(.)을 사용한다. • // 포인터를 통해 클래스 객체의 멤버를 접근하기 • // 위해서는 -> 를 사용한다. • if (r.GetHeight()*r.GetWidth() > • t->GetHeight() * t->GetWidth()) cout<< " r "; • else cout<< " s "; • cout<< "has the greater area" << endl; • } • ----------------------------------- • 프로그램 2.3: Rectangle 객체의 선언과 멤버 함수의 기동을 예시하는 C++ 코드 부분

  9. 2.1 추상 데이타 타입과 C++ 클래스 • ▶ 생성자(constructor)와 파괴자(destructor) • - 생성자와 파괴자: 클래스의 특수한 멤버 함수 • - 생성자: • . 한 객체의 데이타 멤버들을 초기화 • . 클래스 객체가 만들어질 때 자동적으로 실행 • . 해당 클래스의 공용 멤버 함수로 선언 • . 생성자 이름은 클래스의 이름과 동일 • ----------------------------------- • Rectangle::Rectangle(int x, int y, int height, int width) • { • x1=x; y1=y; • h=height; w=width; • } • ----------------------------------- • 프로그램 2.4: Rectangle을 위한 생성자 정의 • - 생성자를 이용한 Rectangle 객체 초기화 • Rectangle r(1,3,6,6); • Rectangle *s = new Rectangle(0,0,3,4); • Rectangle t; // 컴파일에러! -> 묵시생성자 필요

  10. 2.1 추상 데이타 타입과 C++ 클래스 • ----------------------------------- • Rectangle::Rectangle (int x=0, int y=0,// default value • int height=0, int width=0) • : x1 (x), y1(y), h(height), w(width) • {} • ----------------------------------- • 프로그램 2.5: Rectangle 클래스에 대한 생성자 정의 • - 프로그램 2.5의 생성자 • . 데이타 멤버들이 멤버 초기화 리스트에 의해 • 초기화 : 보다 효율적 • - 파괴자: • . 객체가 없어지기 직전 데이타 멤버들을 삭제 • . 클래스 객체가 범위를 벗어나거나 삭제될 때 • 자동적으로 기동 • . 해당 클래스의 공용 멤버로 선언 • . 이름: ~클래스 이름 • . Rectangle r(1,3,6,6); - 삭제시 파괴자가 기동됨 • Rectangle *s = new Rectangle(0,0,3,4); • - 삭제시 파괴자가 기동되지 않음 • . 삭제되는 객체의 한 데이타 멤버가 다른 객체에 대한 포인터인 경우 • -> 지시되는 객체를 삭제하기 위해서는 명시적으로 delete를 사용해야 함

  11. 2.1 추상 데이타 타입과 C++ 클래스 • ▶ 연산자 다중화(operator overloading) • - 하나의 연산자를 여러 의미로 사용 가능 • (예) 연산자 “==“ • . 두 실수(float) 데이타의 동등성 검사 • . 두 정수(int) 데이타의 동등성 검사 • . 두 사각형(Rectangle) 객체 동등성 비교 • 같은 객체 • 위치와 크기가 같은 사각형

  12. 2.1 추상 데이타 타입과 C++ 클래스 • - 클래스 Rectangle을 위한 연산자 “==“의 다중화 • ----------------------------------- • int Rectangle::operator==(constRectangle &s ) • { • ① if (this == &s) return 1; • ② if ((x1 == s.x1) && (y1 == s.y1) && (h == s.h) && (w == s.w)) return 1; • ③ else return 0; • } • ----------------------------------- • 프로그램 2.6: 클래스 Rectangle을 위한 • 연산자 “==“의 다중화 • . this: 멤버 함수를 기동시킨 특정 클래스 객체에 • 대한 포인터(self) • . *this: 클래스 객체 자신 • ① oid비교: “this == &s" • -> 두 객체가 같으면 결과는 1 (참) • ② 값 비교: 데이타 멤버를 개별적으로 비교 • -> 두 객체가 같으면 1 (참) • ③ 아니면 0 (거짓)

  13. 2.1 추상 데이타 타입과 C++ 클래스 • - Rectangle 객체를 cout으로 출력하기 위한 • 연산자 “<<“의 다중화 • ----------------------------------- • ostream& operator <<(ostream& os, Rectangle& r) • { • os<<"Position is: "<<r.x1 << " "; • os<< r.y1 <endl; • os<<"Height is: "<<r.h<<endl; • os<<"Width is: “<<r.w<<endl; • return os; • } • ----------------------------------- • 프로그램 2.7: 클래스 Rectangle을 위한 연산자 “<<“의 • 다중화 • . 연산자 << : Rectangle의 friend • . cout<< r; 의 출력 예 • Position is: 1 3 • Height is: 6 • Width is: 6

  14. 2.1 추상 데이타 타입과 C++ 클래스 • ▶ 기타 내용 • - C++의 struct • . 묵시적 접근 레벨 = public (cf. class에서는 private) • . C의 struct에 대한 일반화 (멤버 함수도 정의 가능) • - union • . 제일 큰 멤버에 맞는 저장장소 할당 • . 보다 효율적으로 기억장소 사용 • - static(정적)클래스 데이타 멤버 • . 클래스에 대한 전역 변수: 오직 하나의 사본 • 모든 클래스 객체는 이를 공유 • . 정적 데이타 멤버는 클래스 외부에서 정의 • ▶ ADT와 C++ 클래스 • - ADT와의 차이: C++의 일부 연산자들은 • 해당 클래스의 멤버 함수로 존재하지 않음 • -> 보통의 C++ 함수로 외부에서 선언 • (해당 클래스에서 friend 선언)

  15. 2.1 추상 데이타 타입과 C++ 클래스 • - 예제 2.1 [추상 데이타 타입 NaturalNumber] • ----------------------------------- • class NaturalNumber{ • // 컴퓨터에서 0부터 최대 정수(MAXINT)까지의 • // 순서화된 정수의 부분 • public: • NaturalNumberZero(); • // 0을 반환 • Boolean IsZero(); • // *this가 0이면 TRUE, 아니면 FALSE를 반환 • NaturalNumberAdd(NaturalNumbery); • // *this +y와 MAXINT에서 작은 값을 반환 • Boolean Equal(NaturalNumbery); • // *this==y이면 TRUE, 아니면 FALSE를 반환 • NaturalNumberSuccessor(); • // *this가 MAXINT이면 MAXINT, • // 아니면 *this +1을 반환 • NaturalNumberSubstract(NaturalNumbery); • // *this <y이면 0, 아니면 *this-y를 반환 • }; • ----------------------------------- • ADT1.2: NaturalNumber추상 데이타 타입

  16. 2.2 추상 데이타 타입으로서의 배열

  17. 2.2 추상 데이타 타입으로서의 배열 • - 일련의 연속적인 메모리 위치: 구현 중심 • - 배열 ADT • . <인덱스,값>: <index,value>의 쌍 집합 • index -> value : 대응, 사상(mapping) • ↑ • same data type • . index: finite ordered set of j-dimensions (j≥1) • - C++ 배열 • . 인덱스 집합이 0부터 시작 • . 배열의 인덱스 범위를 확인하지 않음 • (예) float example[n]; • i번째 원소값 • -> example[i], *(example+i) • . 함수 • GeneralArray(j-dimension, j-range list, initial value) • Retrieve(index) • Store(index, item)

  18. ------------------------------------- • Class GeneralArray { • // objects: IndexSet의 index 각 값에 대하여 float 타입의 • // value가 존재하는 <index, value>쌍의 집합. • // IndexSet는 일차원 또는 다차원의 유한 순서 집합 • // 일차원의 경우 0,···,n-1와 이차원 배열 (0,0), (0,1), • // (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2), 등이다. • public: • GeneralArray (int j, RangeListlist, • float initValue= defaultValue); • // 생성자 GeneralArray는 j 차원의 실수 배열을 생성 • // k번째 인덱스의 범위는 list의 k번째 원소에 의해정해짐 • // 인덱스 집합의 각 인덱스 i에 대해 <i, initValue>를 • // 배열에 삽입 • float Retrieve(index i); • // if (i가 배열의 index 집합에 있는 경우) • // return 배열 내 i와 연관된 실수값 • // else 오류를 출력 • void Store(index i, float x); • // if (i가 배열의 index 집합에 있는 경우) • // 배열 내에 있는 <i, y>의 쌍을 삭제하고 • // 새로운 쌍인 <i, x>를 삽입 • // else 오류를 출력 • }; // GeneralArray의 끝 • -------------------------------------- • ADT2.1 추상 데이타 타입 GeneralArray

  19. 2.3 다항식 추상 데이타 타입

  20. 2.3 다항식 추상 데이타 타입 • ▶ ordered list, linear list • : 순서 리스트, 선형 리스트 • - examples • •한 주일의 요일: (일,월,화,수, .., 토) • •카드 한 벌의 값: (Ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King) • •건물 층: (지하, 로비, 1층, 2층) • •미국의 WWII참전년도: (1941, 1942, 1943, 1944, 1945) • •스위스의 2차 세계대전 참전 년도: () • - 리스트 형태: (a0, a1, ... , an-1) • - 공백 리스트: () → 포함된 항목이 없음 • - 리스트에 대한 연산 • •길이 n의 계산 • •리스트의 항목을 왼쪽에서 오른쪽(오른쪽에서 왼쪽)으로 읽기 • • i번째 항목을 검색, 0 ≤i<n • • i번째 항목을 대체, 0 ≤i<n • • i번째 위치에 새항목 삽입, 0 ≤i<n • •i번째 항목을 삭제, 0 ≤i<n

  21. 2.3 다항식 추상 데이타 타입 • - 순서 리스트의 일반적인 구현 • • 배열을 이용 • • 인덱스 i → ai, 0≤i<n • ... i, i+1, ... • ... ai, ai+1, ... • • 순차적 사상(sequential mapping) • • 문제점: 삽입, 삭제시 오버헤드 • ▶ 다항식 (polynomial) • - A(x) = ∑aixei: 항의 합 • ai: 계수(coefficient), ai ≠ 0 • ei: 지수(exponent), unique, ≥0 • x : 변수(variable) • A(x) = 3x20+ 2x5+ 4 , • B(x) = x4+ 10x3+ 3x2+ 1 • - 차수(degree): 가장 큰 지수 • - 다항식의 합과 곱 • A(x) = ∑aixi • B(x) = ∑bixi • A(x) + B(x) = ∑(ai+ bi)xi • A(x) •B(x) = ∑(aixi· ∑(bjxj))

  22. 2.3 다항식 추상 데이타 타입 • - 다항식 추상 데이타 타입 • ------------------------------------- • ClassPolynomial { • // objects: P(x)=a0 xe0 + ··· +an xen; <ei , ai>의 • //순서쌍으로된 집합. • // 여기서 ai∈Coefficient 이고, ei ∈ Exponent • // Exponent는 ≥0인 정수로 가정 • public: • Polynomial(); • // 다항식 p(x)=0를 반환 • int operator!(); • // *this가 0의 다항식이면 1을 아니면 0을 반환 • Coefficient Coef(Exponent e); • // *this에 있는 e의 계수를 반환 • Exponent LeadExp(); • // *this에서 가장 큰 지수를 반환 • Polynomial Add(Polynomial poly); • // *this와 poly의 합을 반환 • Polynomial Mult(Polynomial poly); • // *this와 poly의 곱을 반환 • float Eval(float f); • // *this에 f를 대입한 값을 계산하여 그 결과를 반환 • } ; // polynomial 정의 끝 • ------------------------------------- • ADT2.2 polynomial 추상 데이타 타입

  23. 2.3 다항식 추상 데이타 타입 • ▶ 다항식 표현 • - 가정: 서로 다른 지수들은 내림차순으로 정돈 • [표현 1]모든 차수에 대한 계수만 저장, 계수 배열 크기 는 최대로 • - Polynomial의 전용 데이타 멤버 선언 • private: • int degree; //degree ≤MaxDegree • float coef[MaxDegree+ 1]; • - a가 Polynomial 클래스 객체, n ≤MaxDegree • a.degree= n • a.coef[i] = an-i, 0 ≤i ≤n • - a.coef[i]는 xn-i의 계수, 각 계수는 지수의 내림차순으로 저장 • - 장점: 다항식에 대한 연산 알고리즘이 간단 • - 단점: 저장 공간 낭비 • (a.degree가 MaxDegree보다 아주 작을 때)

  24. 2.3 다항식 추상 데이타 타입 • [표현 2]모든 차수에 대한 계수만 저장, 계수 배열 크기는 • 실제 차수 크기로 • - Polynomial의 전용 데이타 멤버 선언 • private: • int degree; • float *coef; • - 생성자를 Polynomial에 추가 • Polynomial::Polynomial(int d) • { • degree=d; • coef=new float[degree+1]; • } • - 단점: 희소 다항식에서 기억 공간 낭비 • (예) 다항식 x1000+1 • -> coef에서 999개의 항목은 0

  25. 2.3 다항식 추상 데이타 타입 • [표현 3] 0이 아닌 계수-지수 쌍만 저장 • - 다항식 • A(x) = bm xem + bm-1 xem-1 + ··· + b0 xe0 • bi : A의 0이 아닌 계수 • ei : 지수, 내림차순. em > em-1 > ··· > e0≥ 0. • . A의 모든 계수가 0이 아니면: • m=n, ei=i, 0 ≤ i ≤ n에 대해서 bi = ai • . an만이 0이 아니면, m=0,b0 = an 이고e0 = n • - 모든 다항식은 배열 termArray를 이용해 표현 • . termArray의 각 원소는 term 타입 • . Polynomial의 정적 클래스 데이터 멤버로 선언 • class Polynomial; • class term { • friend Polynomial; • private: • float coef; // 계수 • int exp; // 지수 • }; • - Polynomial의 전용 데이타 멤버 선언 • private: • static term termArray[MaxTerms]; • static int free; • int Start, Finish;

  26. 2.3 다항식 추상 데이타 타입 • - 클래스 정의 외부의 정적 클래스 멤버 정의 • term Polynomial::termArray[MaxTerms]; • int Polynomial::free = 0; • //termArray에서 다음 자유공간의 위치 • - 두개의 다항식 A(x)=2x1000+1, • B(x)=x4+10x3+3x2+1 표현 • 그림 2.1 두 다항식의 배열 표현 • - n개의 0이 아닌 항을 가진 다항식 A는 • A.Finish= A.Start+n-1의 식을 만족하는 • A.Start와 A.Finish를 가짐 • -> A가 0이 아닌 항이 없을 경우 A.Finish= A.Start-1 • - termArray에 저장될 수 있는 다항식수는 MaxTerms • - 장점: 많은 항이 0인 경우 우수 • - 단점: 모든 항이 0이 아닌 경우 • 표현 2보다 두배의 저장 장소 사용

  27. 2.3 다항식 추상 데이타 타입 • ▶ 다항식 덧셈 • - C=A+B를 구하는 C++ 함수 • 함수 Add(프로그램 2.8): A(x)와 B(x)를 항별로 더하여 C(x)를 만드는 함수 • - 다항식은 0이 아닌 항만 저장

  28. 2.3 다항식 추상 데이타 타입 • Polynomial Polynomial::Add(Polynomial B){ • // A(x)(*this의 값)와 B(x)를 더한 결과를 반환한다. • Polynomial C; int a = Start; int b = B.Start; • C.Start= free; float c; • while ((a<=Finish) && (b<=B.Finish)) • witch(compare(termArray[a].exp,termArray[b].exp)){ • case '=': • c = termArray[a].coef+ termArray[b].coef; • if (c) NewTerm(c, termArray[a].exp); • a++; b++; break; • case '<': • NewTerm(termArray[b].coef, termArray[b].exp); • b++; break; • case '>': • NewTerm(termArray[a].coef, termArray[a].exp); • a++; • } • for (; a<=Finish; a++) // A(x)의 나머지 항들을 추가한다. • NewTerm(termArray[a].coef, termArray[a].exp); • for (; b<=B.Finish; b++) // B(x)의 나머지 항들을 추가한다. • Newterm(termArray[b].coef, termArray[b].exp); • C.Finish= free - 1; • return C; • }// Add의 끝 • ------------------------------------ • 프로그램 2.8: 두 다항식 덧셈

  29. 2.3 다항식 추상 데이타 타입 • ------------------------------------ • void Polynomial::NewTerm(float c, int e) { • // C(x)에 새로운 항을 첨가 • if (free>=MaxTerms) { • cout<< "Too many terms in polynomials" << endl; • return; • } • termArray[free].coef= c; • termArray[free].exp= e; • free++; • }// NewTerm의 끝 • ------------------------------------- • 프로그램 2.9: 새로운 항의 추가 • 알고리즘 Add 의 분석 : • - m과 n: A와 B에서의 0이 아닌 항의 수 • - 복잡도: O(n+m) • ▶ 다항식을 배열로 표현하는 경우의 문제점 • - 공간의 비효율적 사용 • - 실제 필요한 만큼의 저장공간 사용 • → 동적 메모리 할당 (4장 리스트)

  30. 2.4 희소 행렬

  31. 2.4 희소 행렬 • ▶ 개요 • A[m][n] • - m × n 행렬 A • m : 행의 수 • n : 열의 수 • m × n : 원소의 수 • - m = n : 정방 행렬 • - 특정 원소 • A[i][j] • - 희소 행렬(sparse matrix) • 0이 아닌 원소수 / 전체 원소수 << small • -> 0이 아닌 원소만 저장할 필요 있음 • - 행렬에 대한 연산 • creation • addition • multiplication • transpose

  32. 2.4 희소 행렬 • - 밀집 행렬과 희소 행렬 예 • 그림 2.2: 두 행렬

  33. - 희소 행렬 ADT • ------------------------------------- • Class SparseMatrix{ • // objects: 3원소쌍 <행, 열, 값>의 집합이다. 여기서, 행과 • //열은 정수이고 이 조합은 유일하며, 값 또한 정수이다. • public: • SparseMatrix(int MaxRow, it MaxCol); • // 이 생성자 함수는MaxItems=MaxRowx MaxCol을 • //저장할 수 있는 SparseMatrix를 생성한다. 여기서 최대 • //행의 수 는 max_row 이고 최대 열 수는 max_col이다. • SparseMatrixTranspose(); • // *this의 모든 3원소 쌍의 행과 열의 값을 서로 교환하여 • //얻은 행렬을 반환한다. • SparseMatrixAdd(SparseMatrixb); • // if a(*this)와 b의 차원이 같으면대응 항들 즉, 같은 행과 • //열의 값을 가진 항들을 더해서 만들어진 행렬을 반환 • //하고, else 오류를 발생한다. • SparseMatrixMultiply(SparseMatrixb); • // if a(*this)의 열의 수와 b의 행의 수가 같으면다음 공식 • //에 따라 a와 b를 곱해서 생성된 행렬 d를반환하고 • // 행렬 d : d(i,j)=(a[i][k]·b[k][j]) • // 여기서 d(i,j)는 (i,j)번째 요소 • // else 오류를 발생한다. • }; • ----------------------------------------- • ADT2.3 SparseMatrix추상 데이타 타입

  34. 2.4 희소 행렬 • ▶효율적인 희소 행렬 표현 • - 표현 방법 • i. <행, 열, 값> 3원소 쌍(triple) • ii. 행의 수 • iii. 열의 수 • iv. non-zero 원소의 수 • v. 순서 (행우선 또는 열우선) : 행 또는 열의 오름순 • - C++ 표현 • class SparseMatrix; // 전방 선언 • class MatrixTerm { • friend class SparseMatrix • private: • int row, col, value; • }; • - 클래스 SparseMatrix내부 정의 • private: • int Rows, Cols, Terms; • MatrixTermsmArray[MaxTerms]; • . Rows: 행의 수 • . Cols: 열의 수 • . Terms: 0이 아닌 항의 총 수

  35. 2.4 희소 행렬 • - 그림 2.2(b)의 행렬의 smArray표현 • ------------------------------------- • 행열값 • smArray[0] 0 0 15 • [1] 0 3 22 • [2] 0 5 -15 • [3] 1 1 11 • [4] 1 2 3 • [5] 2 3 6 • [6] 4 0 91 • [7] 5 2 28 • (a) • 행열값 • smArray[0] 0 0 15 • [1] 0 4 91 • [2] 1 1 11 • [3] 2 1 3 • [4] 2 5 28 • [5] 3 0 22 • [6] 3 2 -6 • [7] 5 0 -15 • (b) • ------------------------------------- • 그림 2.3 3원소 쌍으로 저장된 희소 행렬과 전치행렬.

  36. 2.4 희소 행렬 • ▶ 행렬의 전치 • - 원래의 행렬 각 행 i에 대해서원소 <i, j, 값> 을 가져와서전치행렬의 원소 <j, i, 값> 으로 저장 • (예) (0, 0, 15) -> (0, 0, 15) • (0, 3, 22) -> (3, 0, 22) • (0, 5, -15) -> (5, 0, -15) • (1, 1, 11) -> (1, 1, 11) • . 문제점: 올바른 순서 유지위해 기존원소 이동 알고리즘 for (열 j에 있는 모든 원소에 대해) 원소<i, j, 값>을 원소<j, i, 값>에 저장

  37. 2.4 희소 행렬 • ------------------------------------- • SparseMatrixSparseMatrix::Transpose() { • // a (*this)의 전치 행렬을 반환 • SparseMatrixb; • b.Rows= Cols; // b의 행 수 = a의 열 수 • b.Cols= Rows; // b의 열 수 = a의 행 수 • b.Terms= Terms; // b의 원소수 = a의 원소수 • if (Terms > 0) { // 0이 아닌 행렬 • int CurrentB= 0; • for (int c = 0; c < Cols; c++) // 열별로 전치 • for (int i = 0; i < Terms; i++) • // 열 c로부터 원소를 찾는다. • if (smArray[i].col ==c) { • b.smArray[CurrentB].row = c; • b.smArray[CurrentB].col = smArray[i].row; • b.smArray[CurrentB].value = smArray[i].value; • CurrentB++; • } • } // if (Terms >0)의 끝 • return b; • } // Transpose의 끝 • ------------------------------------- • 프로그램 2.10: 행렬의 전치

  38. 2.4 희소 행렬 • - 복잡도: O(terms·columns), O(rows·columns2) • -> 공간 절약을 위해 시간을 희생한 결과 • [note] 단순 2차원 배열 표현시는 • O(rows·columns) • for (intj = 0; j < columns; j++) • for (inti = 0; i < rows; i++) • B[j][i] = A[i][j];

  39. 2.4 희소 행렬 • - 메모리를 조금 더 사용한 개선 알고리즘: • FastTranspose • . 먼저 행렬 a의 각 열에 대한 원소 수를 구함 • -> 즉,전치행렬 b의 각 행의 원소 수를 결정 • . 이 정보에서 전치행렬 b의 각행의 시작위치 구함 • . 원래 행렬 a에 있는 원소를 하나씩 전치 행렬 b의 • 올바른 위치로 옮김 • ROW_SIZE ROW_START • [0] 2 0 • [1] 1 2 • [2] 2 3 • [3] 2 5 • [4] 0 7 • [5] 1 7 • ↑ ↑ • # of terms starting position • in b's row (a's col) of b's row

  40. ------------------------------------------ • SparseMatrixSparseMatrix::FastTranspose() { • // a(*this)를 b로 전치하고 O(terms+columns) 연산 시간이 • 걸린다. • int *RowSize= new int[Cols]; • int *RowStart= new int[Cols]; • SparseMatrixb; • b.Rows= Cols; b.cols= Rows; b.Terms= Terms; • if (Terms>0) { // 0이 아닌 행렬 • // RowSize[i] = b의 행 i에 있는 항의 수를 계산 • for (int i = 0; i<Cols; i++) RowSize[i] = 0; // 초기화 • for (i = 0; i<Terms; i++) RowSize[smArray[i].col]++; • RowStart[0] = 0; // RowStart[i] = b의 행 i의 시작점 • for (i =1; i<Cols; i++) • RowStart[i] = RowStart[i-1] + RowSize[i-1]; • for (i = 0; i<Terms; i++) { // a를 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; • } • ------------------------------------- • 프로그램 2.11 희소 행렬의 빠른 전치 • - 복잡도: O(columns+terms)

  41. 2.4 희소 행렬 • ▶ 행렬 곱셈 • - Result ← A × B • Resultm×p← Am×n× Bn×p • resultij = , 0≦i<m, 0≦j<p • ------------------------------------- • ------------------------------------- • - 순서 리스트로 표현된 두 희소 행렬의 곱셈 • . Result의 원소를 행별로 계산 • -> 이전 계산 원소를 이동하지 않고 저장 • . 행렬 A에서 한 행을 선택하고 j = 0,1,..., B.Col-1에 대해 B의 j열에 있는 모든 원소를 찾음 • . B를 전치 • . A의 i행과 B의 j열의 원소들이 정해지면 다항식 덧셈과 유사한 합병연산 수행

  42. 2.4 희소 행렬 • int SparseMatrix::StoreSum(int sum,int& LastInResult, intr,intc) • { • // sum≠0이면 행과 열의 위치와 함께 • // result의 (LastInResult+1)번 째 항목에 저장된다. • // LastInResult는 증가한다. • // 새로운 항을 위한 가용 메모리가 없으면 1이, • // 그렇지 않으면 0을 호출함수에 반환한다. • if (sum != 0) { • if (LastInResult< MaxTerms-1) { • LastInResult++; • smArray[LastInResult].row = r; • smArray[LastInResult].col = c; • smArray[LastInResult].value = sum; • return 0; • } • else { • cerr<< "Number of terms in product exceeds • MaxTerms" << endl; • return 1; • } • } • else return 0; • } • ------------------------------------ • 프로그램 2.12: 행렬 항의 저장

  43. 2.4 희소 행렬 • ---------------------------------------- • SparseMatrix SparseMatrix::Multiply(SparseMatrix b) • // 두 개의 희소 행렬 A(*this)와 B를 곱하여 Result를 생성 • { • if (Cols != b.Rows) { • cout << "Incompatible matrices" << endl; • return EmptyMatrix(); • } • if ((Terms == MaxTerms) || (b.Terms == MaxTerms)) { • cout << "One additional space in a or b needed" << endl; • return EmptyMatrix(); • } • SparseMatrix bXpose = b.FastTranspose(); • SparseMatrix result; • int currRowIndex = 0, LastInResult = -1, • currRowBegin = 0, currRowA = smArray[0].row; • // 경계 조건 설정 • smArray[Terms].row = Rows; • bXpose.smArray[b.Terms].row = b.Cols; • bXpose.smArray[b.Terms].col = -1; int sum = 0;

  44. while(currRowIndex<Terms) {// result의 행 currRowA를 생성 • int currColB= bXpose.smArray[0].row; • int currColIndex= 0; • while (currColIndex<= b.Terms) { • // a의 행 currRowA에 b의 열 currColB를 곱함 • if (smArray[currRowIndex].row != currRowA) { • // currRowA행의 끝 • if (result.StoreSum(sum, LastInResult, • currRowA, currColB)) • return EmptyMatrix(); // 에러 • else sum = 0; // sum을 재설정 • currRowIndex= currRowBegin; • // 다음 열로 넘어감 • while(bXpose.smArray[currColIndex].row == currColB) • currColIndex++; • currColB= bXpose.smArray[currColIndex].row; • } • else if (bXpose.smArray[currColIndex].row != currColB) • { // b의 열 currColB의 끝 • if (result.StoreSum(sum, LastInResult, currRowA, • currColB)) • return EmptyMatrix(); //에러 • else sum = 0; // sum을 재설정 • //currRowA행을 다음 열과 곱하도록 설정 • currRowIndex= currRowBegin; • currColB= bXpose.smArray[currColIndex].row; • }

  45. else • switch (compare(smArray[currRowIndex].col, • bXpose.smArray[currColIndex].col)) { • case '<' : //행의 다음 항으로 감 • currRowIndex++; break; • case '=' : // sum에 더함 • sum += smArray[currRowIndex].value * • bXpose.smArray[currColIndex].value; • currRowIndex++; currColIndex++; break; • case '>' : // 열 currColB의 다음 항으로 감 • currColIndex++; • } // switch의 끝 • } // while(currColIndex <= b.Terms)의 끝 • while (smArray[currRowIndex].row == currRowA) • // 다음 행으로 감 • currRowIndex++; • currRowBegin= currRowIndex; • currRowA= smArray[currRowIndex].row; • } // while(currRowIndex < Terms)의 끝 • result.Rows= Rows; result.Cols= b.Cols; • result.Terms= LastInResult+1; • return result; • } // Multiply의 끝 • --------------------------------------- • 프로그램 2.13: 희소 행렬의 곱셈

  46. 2.4 희소 행렬 • - 복잡도: O(∑r(B.Cols •tr+B.Terms)) • = O(B.Cols •A.Terms+A.Rows • B.Terms) • [note] 통상적인 곱셈 알고리즘 • O(A.Rows •A.Cols •B.Cols) • for (int i = 0; i < A.Rows; i++) • for (int j = 0; j < B.Cols; j++) { • sum = 0; • for (int k = 0; k < A.Cols; k++) • sum += (a[i][k] * b[k][j]); • c[i][j] = sum; • }

  47. 2.5 배열의 표현

  48. 2.5 배열의 표현 • ▶ 다차원 배열의 표현 • - addressing formula: A[p1 .. q1 ][p2 .. q2 ], ··· ,[pn .. qn ] A의 총 원소수: • - 특정 원소의 지정: A[i1 ] [i2 ] ,...,[in ] • - 표현 순서: 행우선, 열우선 • . 행우선(row major order) • (예) A[4..5][2..4][1..2][3..4] • 총 원소수: 2*3*2*2=24 • 저장 순서: • A[4][2][1][3], A[4][2][1][4], A[4][2][2][3], A[4][2][2][4] • A[4][3][1][3], A[4][3][1][4], A[4][3][2][3], A[4][3][2][4] • · • · • A[5][4][1][3], A[5][4][1][4], A[5][4][2][3], A[5][4][2][4] • 즉, 4213, 4214, ···, 5423, 5424 • -> 사전순서(lexicographicorder) • 배열 원소 A[i_1 ] [i_2 ] ,...,[i_n ]의 1차원 배열 위치로의 변환 • (예) A[4][2][1][3] -> 위치 0 • A[4][2][1][4] -> 위치 1 • A[5][4][2][4] -> 위치 23

  49. 2.5 배열의 표현 • - 문제의 단순화를 위한 가정: • 차원 i의 인덱스: 0에서 ui –1 (pi = 0, qi = ui – 1) • - 1차원 배열 A[u1] • . α: A[0]의 주소 • . 임의의 원소 A[i]의 주소 : α+ i • 그림 2.5 A[u1]의 순차적인 표현

  50. 2.5 배열의 표현 • - 2차원 배열 A[u1 ][u2 ] • . α: A[0][0]의 주소 • . A[i][0]의 주소: α +i * u2 • . A[i][j]의 주소: α + i * u2 + j • 그림 2.6: A[u1 ][u2 ]의 순차적 표현

More Related