1 / 53

Chapter 2 배열과 구조 (Arrays and Structures) 2009. 3. 23

Chapter 2 배열과 구조 (Arrays and Structures) 2009. 3. 23. 포인터. 포인터 C 언어에서는 모든 타입에 대해 그것의 포인터 타입이 존재 포인터 변수의 값은 메모리 상의 주소 (address) 포인터 관련 연산 주소 / 참조 (address/reference) 연산자 : & 역참조 / 간접참조 (dereferencing/indirection) 연산자 : * 예 int i, *pi

Download Presentation

Chapter 2 배열과 구조 (Arrays and Structures) 2009. 3. 23

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. Chapter 2배열과 구조(Arrays and Structures)2009. 3. 23

  2. 포인터 • 포인터 • C언어에서는 모든 타입에 대해 그것의 포인터 타입이 존재 • 포인터 변수의 값은 메모리 상의 주소(address) • 포인터 관련 연산 • 주소/참조 (address/reference) 연산자: & • 역참조/간접참조 (dereferencing/indirection) 연산자: * • 예 int i, *pi pi = &i; // pi는 i의 주소값을 가짐. 즉, i를 가리킴 // i에 10을 저장하기 i = 10; *pi = 10;

  3. 포인터 • 동적 메모리 할당(dynamic storage allocation) • 프로그램을 작성 시 얼마나 많은 메모리 공간이 필요한지 알 수 없을 때 • 실행-시간 메모리 할당을 위해 heap 이용 • 새로운 메모리 공간이 필요할 때마다 함수 malloc을 호출해서 필요한 양의공간을 할당 받음 int i, *pi; float f, *pf; pi = (int *)malloc(sizeof(int)); pf = (float *)malloc(sizeof(float)); *pi = 1024; *pf = 3.14; printf(“an integer=%d, a float=%f\n”,*pi,*pf); free(pi); free(pf);

  4. ADT로서의 배열 • 배열(array) • 일련의 연속적인 메모리 위치 • 구현 중심의 이해 • 추상 데이터 타입 • <index, value> 쌍의 집합 • 값들은 동일한 타입 • 인덱스와 값 사이의 대응 또는 사상(mappings) • array : i → ai • 수행 가능한 연산 정의 • Array Create(j-dimension, j-range list) • Item Retrieve(array, index) • Array Store(array, index, item)

  5. ADT로서의 배열 Structure Array    Objects : index의 각 값에 대하여 집합 item에 속한 한 값이 존재하는 <index, value>쌍의 집합. index는 일차원 또는 다차원의 유한 순서 집합이다. 예를 들면, 일차원의 경우 {0,‥, n-1}과 이차원 배열 {(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)}, 등이다.   Functions : 모든 A ∈ Array, i ∈ index, x ∈ item, j, size ∈ integer Array Create(j, list)  ::= return j차원의 배열. 여기서 list는 j-tuple(i번째 원소는 i번째 차원의                                크기를 나타냄)이며, item들은 정의되지 않았음. Item Retrieve(A, i)   ::= if (i ∈ index)                                return 배열 A의 인덱스 i값과 관련된 항목.                                else return 에러. Array Store(A, i, x)    ::= if (i ∈ index)                               return 새로운 쌍<i, x>가 삽입된 배열 A.                                else return 에러. end Array

  6. C언어에서의 구현 • C의 일차원 배열 int list[5], *plist[5]; • 정수의 집합 : { list[0], list[1], list[2], list[3], list[4] } • 정수 포인터의 집합 : { plist[0], plist[1], plist[2], plist[3], plist[4] } • 배열 이름 = 포인터 상수(첫번째 원소의 주소) int list2[5]; • list2: list2[0]를 가리키는 포인터 (즉, list2[0]의 주소) • list2+i: list2[i]를 가리키는 포인터 (즉, list2[i]의 주소) • (list2+i) == &list2[i],  *(list2+i) == list2[i]

  7. C언어에서의 구현 • 배열 프로그램의 예 #define MAX_SIZE 100 float sum(float [], int); float input[MAX_SIZE], answer; int i; void main(void) { for (i = 0; i < MAX_SIZE; i++) input[i] = i; answer = sum(input, MAX_SIZE); printf("The sum is: %f\n", answer); } float sum(float list[], int n) // float list[] == float *list { int i; float tempsum = 0; for (i = 0; i < n; i++) tempsum += list[i]; // list[i] == *(list+i) return tempsum; }

  8. C언어에서의 구현 • 호출시 input(=&input[0])은 형식 매개 변수 list에 복사됨 • 즉, list[i] == input[i] • 역참조(dereference) • list[i]가 “=”기호 우측  (list + i)가 가리키는 값 반환 • list[i]가 “=”기호 좌측  값을 (list + i) 위치에 저장 ※ C언어의 매개변수 전달방식 : call-by-value  실 매개변수가 배열 이름인의 경우 배열의 주소를 형식매개변수에 복사함  배열 자체는 복사되지 않음

  9. C언어에서의 구현 • 예제[일차원 배열의 주소 계산] short one[] = {0, 1, 2, 3, 4}; printf1(&one[0], 5) // == print1(one, 5) void print1 (short *ptr, int rows) { /* print out an one-dimensional array using a pointer */ int i; printf (“Address Contents\n”); for (i=0; i<rows; i++) printf(“%8u%5d\n”, ptr + i, *(ptr + i)); // &ptr[i], ptr[i]와 동일 printf(“\n”); }

  10. 동적 할당 배열 #define MALLOC(p, s)\ if(!((p) = malloc(s))) {\ fprintf(stderr, “Insufficient memory”):\ exit(EXIT_FAILURE):\ } #define CALLOC(p, n, s)\ if(!((p) = calloc(n, s))) {\ 메모리를 할당하고 0으로 초기화함 fprintf(stderr, “Insufficient memory”):\ exit(EXIT_FAILURE):\ } #define REALLOC(p, s)\ if(!((p) = realloc(n, s))) {\ 메모리를 재할당 (크기 변경) fprintf(stderr, “Insufficient memory”):\ exit(EXIT_FAILURE):\ }

  11. 동적 할당 배열 • 1차원 배열 동적 생성 예 int i, n, *list; printf(“Enter the number of number to generate: ”); scanf(“%d”, &n”); if (n < 1) { fprintf(stderr, “Improper value of n \n”); exit (EXIT_FAILURE); } MALLOC(list, n * sizeof(int)); ※ n < 1이거나 정렬할 수의 리스트를 저장할 메모리가 충분치 않을 때 실패

  12. 동적 할당 배열 • 2차원 배열 동적 생성 예 • int x[3][5] [1] [4] [0] [2] [3] x x[0] x[1] x[2] int ** make2dArray(int rows, int cols) { /* create a two dimensional rows  cols array */ int **x, i; /* get memory for row pointers */ MALLOC (x, rows * sizeof(int*));; /* get memory for each row */ for (i = 0; i < rows; i++) MALLOC (x[i], cols * sizeof(int)); return x; }

  13. 동적 할당 배열 • 사용 예 • 510 2차원 정수 배열에 대한 메모리 할당 • 이 배열의 [2][4]원소에 정수 6을 지정 int **myArray; myArray = make2dArray(5, 10); myArray[2][4] = 6

  14. 구조체(Structure) 및 공용체(Union) • 구조(structure) : struct • 타입이 다른 데이터들을 그룹화 함 • 데이터 항목들의 집단 - 각 항목은 타입과 이름으로 식별 • 멤버(member) 연산자 . • strcpy(person.name, "james"); • person.age =10; • person.salary = 35000; struct { char name[10]; int age; float salary; } person;

  15. 구조체(Structure) 및 공용체(Union) • typedef 문장을 사용한 구조체 데이터 타입 생성 • 전체 구조의 동등성 검사 :  if (person1 == person2) • 구조 치환 :  person1 = person2 (ANSI C) • strcpy(person1.name, person2.name); • person1.age = person2.age; • person1.salary = person2.salary; typedef struct human_being {        char name[10];      int age;                             float salary;                          };                             /* 변수 선언 */ human_being person1, person2; typedef struct {       char name[10];                int age;                      float salary;       } human_being;                     /* 변수 선언 */ human_being person1, person2;

  16. 구조체(Structure) 및 공용체(Union) • 구조체 속에 또 다른 구조체 정의 • 예 typedef struct { int month; int day; int year; } date ; typedef struct human_being { char name[10]; int age; float salary; date dob; } ; person1.dob.month = 2; person1.dob.day = 11; person1.dob.year = 1944;

  17. 구조체(Structure) 및 공용체(Union) • 공용체(Union) • 공용체에 속한 각 필드들은 메모리 공간을 공유함 • 어느 한 시점에 한 필드만 활동적이 되어 사용 가능 • C에서는 공용체 필드의 올바른 사용 여부를 검사하지 않음 typedef struct gender_type { enum tag_field {female, male} gender; union { int children; int beard; } u ; }; typedef struct human_being { char name[10]; int age; float salary; date dob; gender_type g_info; }; human_being person1, person2; person1.g_info.gender = male; person1.g_info.u.beard = FALSE; person2.g_info.gender = female; person2.g_info.u.children = 4;

  18. 구조체(Structure) 및 공용체(Union) • 자체참조 구조체 (self-referential structure) • 구성요소중 자신을 가리키는 포인터가 존재하는 구조체 typedef struct list { char data; list *link; }; list item1, item2, item3; item1.data = 'a'; item2.data = 'b'; item3.data = 'c'; item1.link = item2.link = item3.link = NULL; item1.link = &item2;구조들을 서로 연결 item2.link = &item3;(item1→ item2→ item3)

  19. 순서 리스트 • 순서 리스트, 선형 리스트(Ordered list, Linear list) • 순서가 있는 원소들의 집합 • 예 • 한 주일의 요일: (일,월,화,수, .., 토) • 카드 한 벌의 값: (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) • 공백 리스트: () -> 포함된 항목이 없음

  20. 순서 리스트 • 리스트에 대한 연산 • 리스트 길이 n의 계산 • 리스트의 항목을 왼쪽에서 오른쪽 (오른쪽에서 왼쪽) 으로 읽기 • i 번째 항목을 검색, 0  i < n • i 번째 항목을 대체, 0  i < n • i 번째 위치에 새 항목 삽입, 0  i <n • i 번째 항목을 삭제, 0  i < n • 순서 리스트의 일반적인 구현 (기억장소 표현) • 순차 사상 (sequential mapping) • 배열 이용 • 물리적 인접성 이용 • 장점: 상수 시간내에 항목 검색/변경 가능 • 문제점: 삽입, 삭제시 오버헤드 • 비순차 사상(non-sequential mapping) • 비연속적 기억장소 위치 • 연결 리스트로 표현 : pointer(즉, link)를 가지는 노드들의 집합

  21. 다항식 추상 데이터 타입 • 다항식 (polynomial) • A(x) = aiXei = anxn+an-1xn-1+...+a1x1+a0x0 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. polynomial 추상 데이터 타입 Structure Polynomial  Objects : P(x) = +・・・+ : <ei, ai>의 순서쌍 집합. 여기서 ai는 Coefficient, ei는 Exponents. ei (≥ 0)는 정수. Function : 모든poly, poly1, poly2 ∈ polynomial,             coef ∈ Coefficients, expon ∈ Exponents에 대해 Polynomial Zero()                           ::= return 다항식, p(x) = 0 Boolean IsZero(poly)                       ::= if (poly) return FALSE                                             else return TRUE Coefficient Coef(poly, expon)       ::= if (expon ∈ poly) return 계수 else return 0 Exponent Lead_Exp(poly)             ::= return poly에서 제일 큰 지수 Polynomial Attach(poly, coef, expon)   ::= if (expon ∈ poly) return 오류 else return <coef, exp>항이 삽입된 다항식poly  Polynomial Remove(poly, expon)   ::= if (expon ∈ poly)                                                    return 지수가 expon인 항이 삭제된 다항식 poly                                                      else return 오류        Polynomial SingleMult(poly, coef, expon) ::= return 다항식 poly‧coef‧xexpon Polynomial Add(poly1, poly2)             ::= return 다항식 poly1 + poly2 Polynomial Mult(poly1, poly2)            ::= return 다항식 poly1‧poly2 end polynomial

  23. Add 연산 /* d = a + b, 여기서 a, b, d는 다항식이다. */ d = Zero(); while (! IsZero(a) && ! IsZero(b)) do { switch COMPARE(Lead_Exp(a), Lead_Exp(b)) { case -1: d = Attach (d, Coef(b, Lead_Exp(b)), Lead_Exp(b)); b = Remove(b, Lead_Exp(b)); break; case 0: sum = Coef(a, Lead_Exp(a)) + Coef(b, Lead_Exp(b)); if (sum) { Attach(d, sum, Lead_Exp(a)); a = Remove(a, Lead_Exp(a)); b = Remove(b, Lead_Exp(b)); } break; case 1: d = Attach(d, Coef(a, Lead_Exp(a)), Lead_Exp(a)); a = Remove(a, Lead_Exp(a)); } } a 또는 b의 나머지 항을 d에 삽입한다.

  24. 다항식의 표현 1 • 가정: 서로 다른 지수들을 내림차순으로 정렬 • [표현 1] 모든 차수에 대한 계수 저장 • 계수 배열 크기는 기정의된 값(최대값)으로 • a: polynomial, n < MAX_DEGREE • a.degree = n • a.coef[i] = an-i, 0 ≤ i ≤ n • 예 • A(x) = x4+10x3+3x2+1   : n = 4 • A = (4, 1, 10, 3, 0, 1)     • 장점: 다항식에 대한 연산 알고리즘이 간단 • 단점: 저장 공간 낭비 • a.degree << MaxDegree 또는 Sparse polynomial의 경우 #define MAX_DEGREE 101 /* 다항식의 최대 차수 + 1 */ typedef struct int degree; float coef[MAX_DEGREE]; } polynomial;

  25. 다항식의 표현 2 • [표현 2] 0이 아닌 계수-지수 쌍 만 저장 • 희소 다항식의 경우 a.coef[MAX_DEGREE]의 대부분이 필요없음 • A(x) = x1000 + 1         : n = 1000 • A = (1000, 1, 0,..., 0, 1)   : 1002 elements                                   ↳ 999 • A(x) = bm-1xe_m-1 + bm-2xe_m-2 + ... + boxe_0 where bi ≠ 0 (0≤i≤m-1), em-1>em-2>...>eo≥0 A = (m, em-1, bm-1, em-2, bm-2, ... , e0, b0) • 예 • A(x) = x4+10x3+3x2+1 : A = (4, 4, 1, 3, 10, 2, 3, 0, 1) • A(x) = x1000 +1 : A = (2, 1000, 1, 0, 1)

  26. 다항식의 표현 2 • 여러 개의 다항식 표현: 모든 다항식을 하나의 전역 배열에 저장 A(x)=2x1000+1 B(x)=x4+10x3+3x2+1 starta finisha startb finishb avail coef exp A(x) : <starta, finisha> finisha = starta + n - 1 • 장점: 많은 항이 0인 경우 우수 • 단점: 모든 항이 0이 아닌 경우 표현 1보다 두 배의 저장 장소 필요 MAX_TERMS 100 /* 항 배열의 크기 */ typedef struct { float coef; int expon; } Polynomial; Polynomial terms[MAX_TERMS]; int avail = 0;

  27. 다항식의 표현 2: Add 연산의 구현 void padd(int starta, int finisha, int startb, int finishb,int *startd, int *finishd); { /* A(x) 와 B(x)를 더하여 D(x)를 생성한다 */ float coefficient; *startd = avail; while (starta <= finisha && startb <= finishb) switch (COMPARE(terms[starta].expon, terms[startb].expon)) { case -1: /* a의 expon이 b의 expon보다 작은 경우 */ attach(terms[startb].coef, terms[startb].expon); startb++; break; case 0: /* 지수가 같은 경우 */ coefficient = terms[starta].coef + terms[startb].coef; if (coefficient) attach(coefficient, terms[starta].expon); starta++; startb++; break; case 1: /* a의 expon이 b의 expon보다 큰 경우 */ attach(terms[starta].coef, terms[starta].expon); starta++; } for( ; starta <= finisha; starta++ ) /* A(x)의 나머지 항들을 첨가한다 */ attach(terms[starta].coef, terms[starta].expon); for( ; startb <= finishb; startb++ ) /* B(x)의 나머지 항들을 첨가한다 */ attach(terms[startb].coef, terms[startb].expon); *finishd = avail-1; }

  28. 다항식의 표현 2: Add 연산의 구현 void attach(float coefficient, int exponent) {/* 새 항을 다항식에 첨가한다. */ if (avail >= MAX_TERMS) { fprintf(stderr, "다항식에 항이 너무 많다."); exit(1); } terms[avail].coef = coefficient; terms[avail++].expon = exponent; }

  29. 다항식의 표현 2: Add 연산의 구현 • 알고리즘 분석 • m, n (>0) : 각각 A와 B의 0이 아닌 항의 수 • while 루프 : O(n+m) • 각 반복마다 starta나 startb 또는 둘 다 값이 증가 • 반복 종료 조건: starta > finisha || startb > finishb (즉, 어느 한쪽이 모두 검사될 때까지 반복) • 반복 횟수 ≤ m+n-1 -> O(n+m) • m+n-1인 경우: A(x) = x2i  , B(x) = x2i+1일 때 • for 루프 :  O(m), O(n) ∴ 총 연산시간 =  O(n+m) • 문제점 • avail = MAX_TERMS일 때 • 불필요한 다항식 제거 후 배열 끝에 연속적인 가용공간 생성 필요 • 데이터 이동 및 각 다항식의 starti, finishi변경 필요

  30. 희소 행렬(Sparse Matrix) • A[m][n]: m  n 행렬 A • m : 행의 수, n : 열의 수, m  n : 원소의 수 • m = n : 정방 행렬(square matrix) • 각 원소 A[i][j]에 대한 접근: O(1) • 2차원 배열로 구현 시 공간 복잡도: O(m·n) • 희소 행렬(sparse matrix) • 0이 아닌 원소 개수 / 전체 원소 개수 << small • 메모리를 효율적으로 사용하기 위해서는 0이 아닌 원소만 저장해야 함 • 행렬에 대한 연산 • creation • addition • multiplication • transpose

  31. 밀집 행렬과 희소 행렬의 예 3 0 1 2 4 5 0 1 2 0 0 0 0 1 1 2 2 3 3 4 4 5 밀집 행렬 희소 행렬

  32. 희소 행렬 추상 데이터 타입(ADT) Structure SparseMatrix  Objects : 3 원소쌍 <행, 열, 값>의 집합. 행, 열, 값은 정수이고, 행과 열의 각 조합은 유일 Function : SparseMatrix Create(int MaxRow, int MaxCol); // MaxRow x MaxCol (=MaxItems)을 저장할 수 있는 SparseMatrix를 생성함 SparseMatrix Transpose(SparseMatrix a); // a의 모든 3원소 쌍의 행과 열의 값을 서로 교환하여 얻은 행렬을 반환함 SparseMatrix Add(SparseMatrix a, SparseMatrix b); // if a와 b의 차원이 같으면 대응 항들, 즉, 같은 행과 열의 값을 // 가진 항들을 더해서 만들어진 행렬을 반환 // else 오류를 발생 SparseMatrix Multiply(SparseMatrix a, SparseMatrix b); // if a의 열의 수와 b의 행의 수가 같으면 d(i,j)= (a[i][k]  b[k][j])인 // 행렬 d를 반환 // else 오류를 발생 end SparseMatrix

  33. 희소 행렬의 효율적인 표현 • 표현 방법 (필요한 정보들) • i. 0이 아닌 값을 갖는 <행, 열, 값> 3원소 쌍(triple) • ii. 행의 수 • iii. 열의 수 • iv. non-zero 원소의 수 • v. 순서: 행우선 순서 또는 열우선 순서 • #define MAX_TERMS 101 • typedef struct { • int row; • int col; • int value; • } term; • term a[MAX_TERMS]; • - a[0].row: the number of rows • - a[0].col: the number of columns • - a[0].value: the total number of • non-zeros • - We choose row-major order • => term들의 순서 리스트로 표현

  34. 희소 행렬의 효율적인 표현 행 열 값 [0] 6 6 8 a 3 0 1 2 4 5 0 [1] 0 0 15 [2] 0 3 22 1 [3] 0 5 -15 2 [4] 1 1 11 3 [5] 1 2 3 4 [6] 2 3 -6 5 [7] 4 0 91 [8] 5 2 28 예제 희소 행렬 순서 리스트 표현

  35. 3 0 1 2 4 5 0 1 2 3 4 5 A의 전치 행렬 AT 예제 희소 행렬 및 전치 행렬 3 0 1 2 4 5 0 1 2 3 4 5 희소 행렬 A

  36. 열 값 [0] a 6 6 8 [1] 0 0 15 [2] 0 4 91 [3] 1 1 11 [4] 2 1 3 [5] 2 5 28 [6] 3 0 22 [7] 3 2 -6 [8] 5 0 -15 A의 전치 행렬 AT 순서 리스트 표현 행 열 값 [0] 6 6 8 a [1] 0 0 15 [2] 0 3 22 [3] 0 5 -15 [4] 1 1 11 [5] 1 2 3 [6] 2 3 -6 [7] 4 0 91 [8] 5 2 28 희소 행렬 A

  37. 희소 행렬의 전치(transpose) • 단순 알고리즘 for (각 행 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) • 문제점: 올바른 순서 유지 위해 기존 원소를 이동해야 함 • 알고리즘 1 for (각 열 j에 대해) 열 j 에 있는 모든 원소 <i, j, 값>을 원소 <j, i, 값>에 저장

  38. 희소 행렬의 전치 알고리즘 1 void transpose(term a[], term b[]) /* a를 전치시켜 b를 생성 */ { int n, i, j, currentb; n = a[0].value;/* a 행렬에 포함된 0이 아닌 원소의 개수 */ b[0].row = a[0].col; /* b의 행 수 = a의 열 수 */ b[0].col = a[0].row; /* b의 열 수 = a의 행 수 */ b[0].value = n;/* b의 원소 수 = a의 원소 수 */ if (n > 0) { /* 0이 아닌 행렬 */ currentb = 1; for (i = 0; i < a[0].col; i++) /* a의 각 열에 대해 반복 */ for (j = 1; j <= n; j++) /* 모든 원소들을 검사하여*/ if (a[j].col == i) { /* i 열에 속한 원소들을 찾음 */ /* 발견된 원소를 b에 추가 */ b[currentb].row = a[j].col; b[currentb].col = a[j].row; b[currentb].value = a[j].value; currentb++; } } }

  39. 희소 행렬의 전치 알고리즘 1 • 시간 복잡도: O(columns  elements) = O(rows  columns2) • [Note] 희소 행렬을 단순한 2차원 배열로 표현할 경우 전치 방법 for (int j = 0; j < columns; j++) for (int i = 0; i < rows; i++) B[j][i] = A[i][j];  O(rows  columns) • 공간 절약을 위해 시간을 희생한 결과

  40. 희소 행렬의 전치 알고리즘 2 • 메모리 공간을 조금 더 사용한 알고리즘: FastTranspose • 먼저, 행렬 a의 각 열에 대한 원소 수를 구함 • 즉, 전치 행렬 b의 각 행의 원소 수를 결정 • 이 정보로부터 전치 행렬 b의 각 행의 시작 위치를 구함 • 행렬 a에 있는 원소를 하나씩 전치 행렬 b의 올바른 위치로 옮김 • 구현 방법: 부가적인 배열 이용 • row_terms[i]: the number of elements in the row i of the result matrix b • starting_pos[i]: the starting point of the elements in the row i in the sparse matrix representation of b  결과 행렬에 row = i 인 원소를 저장할 때 마다 1 증가시켜, 다음 원소의 저장 위치를 가리키도록 함

  41. 희소 행렬의 전치 알고리즘 2 행 열 값 행 열 값 [0] 6 6 8 [0] b 6 6 8 a [1] 0 0 15 [1] 0 0 15 [2] 0 3 22 [2] 0 4 91 [3] 0 5 -15 [3] 1 1 11 [4] 1 1 11 [4] 2 1 3 [5] 1 2 3 [5] 2 5 28 [6] 2 3 -6 [6] 3 0 22 [7] 4 0 91 [7] 3 2 -6 [8] 5 2 28 [8] 5 0 -15 0, 1, 2, 3, 4, 5 행: row_terms[] = {2, 1, 2, 2, 0, 1} starting_pos[] = {1, 3, 4, 6, 8, 8}

  42. 희소 행렬의 전치 알고리즘 2 void fast_transpose(term a[], term b[]) /* a를 전치시켜 b에 저장 */ { int row_terms[MAX_COL], starting_pos[MAX_COL]; int i, j, num_col = a[0].col, num_terms = a[0].value; b[0].row = a[0].col; b[0].col = a[0].row; b[0].value = a[0].value; if (num_terms > 0) { /* 0이 아닌 행렬 */ for(i = 0; i < num_cols; i++)row_terms[i] = 0; for(i = 1; i <= num_terms; i++) row_terms[a[i].col]++; starting_pos[0] = 1; for(i = 1; i < num_cols; i++) starting_pos[i] = starting_pos[i-1] + row_terms[i-1]; for(i = 1; i <= num_terms; i++) { j = starting_pos[a[i].col]++; b[j].row = a[i].col; b[j].col = a[i].row; b[j].value = a[i].value; } } }

  43. 희소 행렬의 전치 알고리즘 2 • 시간 복잡도: O(columns + elements) = O(rows  columns) 그러나, 희소 행렬에서 elements는 일반적으로 rows  columns 보다 훨씬 작으므로 2차원 배열 알고리즘 보다 빠름 (즉, 시간과 공간을 동시에 절약하는 효과를 거둘 수 있음)

  44. 행렬의 곱셈 • Result A  B • Result(mp) A(mn)  B(np) • [note] 통상적인 곱셈 알고리즘 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; }  O(A.Rows • A.Cols • B.Cols)

  45. 행렬의 곱셈 • 순서 리스트로 표현된 두 희소 행렬의 곱셈 • 결과 행렬(순서 리스트 표현)의 원소들을 행-우선 순서대로 계산 • 계산 및 저장된 원소들을 이동할 필요 없음 • 행렬 A에서 한 행을 선택하고, j = 0,1,..., cols_b-1에 대해 B의 j열에 있는 모든 원소를 찾아서 벡터 내적을 반복 계산해야 함 • 효율적인 계산을 위해 우선 행렬 B에 대한 전치 행렬을 구함 • B의 j열의 원소들을 순서대로 찾을 수 있음 (B의 j열 = BT의 j행) • A의 i행과 BT의 j행(= B의 j열)의 원소들이 정해지면 다항식 덧셈과 유사한 합병 연산 수행 • 알고리즘 및 시간 복잡도 계산 • 교재 참조 • O(B.Cols • A.Terms + A.Rows • B.Terms) => 최악의 경우 O(A.Rows • A.Cols • B.Cols) 이나, A, B가 희소 행렬이면 일반적인 알고리즘보다 훨씬 빠름

  46. 다차원 배열의 표현 • 배열의 원소 수 : A[upper0][upper1]...[uppern-1]       =     • 예: A[10][10][10] → 10・10・10 = 1000 개 • 행 우선 순서(row major order) • A[upper0][upper1] A[0][0], A[0][1], ⋯ , A[0][upper1-1]    ⋯               row0              row1  row2   row_upper0-1 • 열 우선 순서(column major order) A[0][0], A[1][0], ⋯, A[upper0-1][0]    ⋯               col0                col1    col2       col_upper1-1

  47. 다차원 배열의 표현 • 원소의 메모리 주소 계산 (2차원 배열 – 행우선 표현) • α = A[0][0]의 주소 A[i][0]의 주소 = α + i·upper1          A[i][j]의 주소 = α + i·upper1 + j • 주소 계산 (3차원 배열 – 행우선 표현) • A[upper0][upper1][upper2] • 2차원 배열upper1× upper2 → upper0개 A[i][0][0] 주소 = α + i·upper1·upper2      A[i][j][k] 주소 = α + i·upper1·upper2 + j ·upper2 + k

  48. 다차원 배열의 표현 • 주소 계산 (n차원 배열): A[upper0][upper1]...[uppern-1] • α =  A[0][0]...[0]의 주소 A[i0][0]...[0] 주소 = α + i0upper1upper2...uppern-1 A[i0][i1][0]...[0] 주소= α + i0upper1upper2...uppern-1 + i1upper2upper3...uppern-1 A[i0][i1]...[in-1] 주소 = α + i0upper1upper2...uppern-1 + i1upper2upper3...uppern-1 + i2upper3upper4...uppern-1 ⋮ + in-2uppern-1 + in-1 = α +

  49. 문자열 추상 데이타 타입 • 문자열(string): S = s0, s1, …, sn-1의 형태, • si : 문자 집합의 원소 • n = 0 : 공백 또는 널 문자열 • 연산 • 생성, 문자열의 읽기 또는 출력 • 두 문자열 접합(concatenation), 문자열 복사 • 문자열 비교 • 문자열에 일부 문자열 삽입 • 문자열로부터 일부 문자열 삭제 • 문자열에서 특정 패턴 식별

  50. 문자열 추상 데이타 타입 structure String objects : 0개 이상의 문자들의 유한 순서 집합 functions : String Null(int m); // 최대 길이가 m인 문자열 (Null로 초기화) int Compare(String s, String t); // if (s와 t가 동등하면) return 0 // else if (s가 t에 선행하면) return -1 else return 1 Boolean IsNull(String s); // if s가 Null 문자열이면 return TRUE // else return FALSE int Length(String s); // s의 문자수를 반환 String Concat(String s, String t); // s뒤에 t를 붙인 문자열을 반환 String Substr(String s, int i, int j); // s에서 i,i+1,...,i+j-1의 위치에 있는 j개의 문자열을 반환 // 이들이 유효한 위치가 아니면 공백 문자열을 반환 int nfind (String s, String pat); // s의 i에서 시작하는 부분문자열이 pat과 일치하는 경우 인덱스 i를 반환 // pat이 공백이거나 s의 부분문자열이 아닌 경우에는 -1을 반환

More Related