Chapter 2 배열과 구조 (Arrays and Structures)

Slides:



Advertisements
Similar presentations
Ⅰ. 연산자 Ⅱ. 제어 구조. 연산자 : 할당 연산자 - 사용자가 정의한 변수에 임의의 값을 저장하는 기능 strvar = strVar1+ “ Hello ”
Advertisements

Chapter 12. 배열. 배열  동일한 항목들이 동일한 크기로 연속적으로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는 자료 구조.
1 08 배열. 한국대학교 객체지향연구소 2 C 로 배우는 프로그래밍 기초 2 nd Edition 배열  동일한 자료유형의 여러 변수를 일괄 선언  연속적인 항목들이 동일한 크기로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는.
1. 2 차원 배열  배열은 동일한 데이터 유형으로 여러 개의 변수를 사용할 경우 같은 이 름으로 지정하여 간편하게 사용할 수 있도록 하는 것으로서 앞에서 1 차원 배열을 공부하였습니다.  2 차원 배열은 바둑판을 생각하면 되며, 1 차원 배열에서 사용하는 첨자를 2.
제 2 장 : 배열과 구조 이 형 원 강릉대학교 컴퓨터공학과
배열과 ADT(1/2) 연속된 메모리 위치의 집합 <index, value>쌍의 집합
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
제14장 동적 메모리.
희소 행렬(sparse matrix) mn matrix A ≡ A[MAX_ROWS][MAX_COLS] 희소행렬
Report #5 - due: 4/13 다음 10*5의 희소 행렬 A, B를 고려하라.
제2장 배열과구조.
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
5 순차 자료구조 방식.
C로 쉽게 풀어쓴 자료구조 © Copyright 생능출판사 2011
C로 쉽게 풀어쓴 자료구조 © Copyright 생능출판사 2005
연결리스트(linked list).
제 9 장 구조체와 공용체.
제2장 배열과구조.
시스템 생명 주기(System Life Cycle)(1/2)
컴퓨터 프로그래밍 기초 [Final] 기말고사
배열과 ADT(1/2) 연속된 메모리 위치의 집합 <index, value>쌍의 집합
Chapter 03 배열, 구조체, 포인터.
시스템 생명 주기(System Life Cycle)(1/2)
C로 쉽게 풀어쓴 자료구조 © Copyright 생능출판사 2005
자료 구조: Chapter 3 배열(1) 순천향대학교 컴퓨터공학과 하 상 호.
자료 구조: Chapter 3 배열(1) 순천향대학교 컴퓨터공학과 하 상 호.
자료 구조: Chapter 3 (2)구조체, 포인터
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
개정판 누구나 즐기는 C언어 콘서트 제9장 포인터 출처: pixabay.
CHAP 3:배열, 구조체, 포인터.
제 3 장 선형 리스트 3.1 선형 리스트 3.2 연결 리스트 3.3 다항식.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express Slide 1 (of 13)
5장. 참조 타입.
P150 문제를 프로그래밍 할 것 Source file (헤더파일포함), 실행화면 (학번_이름_1.txt)
Dynamic Memory and Linked List
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
Chapter 2:: Array, Structure, and Pointer
8장 함수 함수의 필요성 라이브러리 함수와 사용자 정의 함수 함수의 정의, 원형, 호출 배열을 함수 인자로 전달 재귀호출.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
프로그래밍 랩 – 7주 리스트.
자료구조 구현을 위한 C 프로그래밍 기법, 순차 자 료구조
14장. 포인터와 함수에 대한 이해.
11장. 1차원 배열.
Introduction To Data Structures Using C
자료구조: CHAP 7 트리 –review 순천향대학교 컴퓨터공학과 하 상 호.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
Report #3 - due: 4/6 100*100의 2개의 희소 행렬 A, B를 전달 받아서 이들의 덧셈을 구하고, 그 결과의 행렬 C를 반환하는 add_sparse_matrix(A, B, C)를 다음과 같이 작성하라. 희소 행렬은 sparse_matrix 타입으로 표현된다.
Java의 정석 제 5 장 배 열 Java 정석 남궁성 강의 의
Quiz #7 다음 수들을 합병 정렬과 퀵 정렬 알고리즘을 이용하여 오름 차순으로 정렬하였을 때, 데이터 이동 회수를 각각 구하라. 여러분은 정렬 과정을 단계별로 보이면서 이동 회수를 추적해야 한다. 단, 퀵 정렬시에 피봇으로 배열의 왼쪽 첫 번째 원소를 선택한다. 5.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
3장. 변수와 연산자 교안 : 전자정보통신 홈페이지 / 커뮤니티/ 학술세미나
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
제 3 강.
처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 7 장 배열.
8주차: Strings, Arrays and Pointers
데이터 동적 할당 Collection class.
4장. 데이터 표현 방식의 이해. 4장. 데이터 표현 방식의 이해 4-1 컴퓨터의 데이터 표현 진법에 대한 이해 n 진수 표현 방식 : n개의 문자를 이용해서 데이터를 표현 그림 4-1.
토론을 위한 질문 배열의 이름에는 무엇이 저장되는가? C언어에서 배열 추상데이터의 store는 어떻게 구현 되는가?
7주차: Functions and Arrays
컴퓨터 프로그래밍 기초 - 9th : 배열 / 포인터 -
구조체(struct)와 공용체(union)
Summary of Pointers and Arrays
Numerical Analysis Programming using NRs
제 4 장 Record.
어서와 C언어는 처음이지 제21장.
개정판 누구나 즐기는 C언어 콘서트 제13장 동적 메모리 출처: pixabay.
Pointers summary.
6 객체.
2019 2학기 9장 배열과 포인터 1. 주소, 주소연산자(&) 2. 포인터, 역참조연산자(*) 3. 배열과 포인터.
Presentation transcript:

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

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

포인터 동적 메모리 할당(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);

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

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. end Array

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] 변 수 메모리 주소 list[0] 기본주소 = a list[1] a + sizeof(int) list[2] a + 2 ·sizeof(int) list[3] a + 3 ·sizeof(int) list[4] a + 4 ·sizeof(int)

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;

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

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”); } 주소 1228 1230 1232 1234 1236 내용 1 2 3 4

동적 할당 배열 #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):\ }

동적 할당 배열 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이거나 정렬할 수의 리스트를 저장할 메모리가 충분치 않을 때 실패

동적 할당 배열 2차원 배열 동적 생성 예 int ** make2dArray(int rows, int cols) int x[3][5] [0] [1] [2] [3] [4] 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; }

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

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

구조체(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;

구조체(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;

구조체(Structure) 및 공용체(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;

구조체(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)

순서 리스트 순서 리스트, 선형 리스트(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) 공백 리스트: () -> 포함된 항목이 없음

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

다항식 추상 데이터 타입 다항식 (polynomial) 차수(degree): 가장 큰 지수 다항식의 합과 곱 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))

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

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));             }         case 1:             d = Attach(d, Coef(a, Lead_Exp(a)), Lead_Exp(a));             a = Remove(a, Lead_Exp(a));     } } a 또는 b의 나머지 항을 d에 삽입한다.

다항식의 표현 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;

다항식의 표현 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)

다항식의 표현 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; 2 1 10 3 1000 4

다항식의 표현 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; }

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

다항식의 표현 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 변경 필요

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

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

희소 행렬 추상 데이터 타입(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를 반환 end SparseMatrix

희소 행렬의 효율적인 표현 표현 방법 (필요한 정보들) 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들의 순서 리스트로 표현

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

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

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

희소 행렬의 전치(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, 값>에 저장

희소 행렬의 전치 알고리즘 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++;               }     } }

희소 행렬의 전치 알고리즘 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) 공간 절약을 위해 시간을 희생한 결과

희소 행렬의 전치 알고리즘 2 메모리 공간을 조금 더 사용한 알고리즘: FastTranspose 즉, 전치 행렬 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 증가시켜, 다음 원소의 저장 위치를 가리키도록 함

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

희소 행렬의 전치 알고리즘 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;          }                     } }

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

행렬의 곱셈 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)

행렬의 곱셈 순서 리스트로 표현된 두 희소 행렬의 곱셈 결과 행렬(순서 리스트 표현)의 원소들을 행-우선 순서대로 계산 계산 및 저장된 원소들을 이동할 필요 없음 행렬 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가 희소 행렬이면 일반적인 알고리즘보다 훨씬 빠름

다차원 배열의 표현 배열의 원소 수 : 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

다차원 배열의 표현 원소의 메모리 주소 계산 (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

다차원 배열의 표현 주소 계산 (n차원 배열): A[upper0][upper1]...[uppern-1]   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 = α +

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

문자열 추상 데이타 타입 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을 반환

C 언어의 문자열 구현 내부적으로는 Null 문자(\0)로 끝나는 문자 배열로 표현 문자열 상수는 char* 타입의 변수에 지정 (예) char* str = "abc" 대부분의 C 컴파일러는 여러 가지 문자열 함수를 포함하는 라이브러리를 제공함 그림 2.8 참조 char s[] = “dog”; char t[] = “house”; s[0] s[1] s[2] s[3] t[0] t[1] t[2] t[3] t[4] t[5] d o g \0 h o u s e \0

문자열 삽입 함수 예 void strnins (char *s, char *t, int i) (Program 2.12) 초기 상태 s a m o b i l e \0 t u t o \0 temp \0 (a) 함수 strncpy(temp, s, i) 호출 후 temp a \0 (b) 함수 strcat(temp, t) 호출 후 temp a u t o \0 (c) 함수 strcat(temp, (s+i)) 호출 후 temp a u t o m o b i l e \0 (d) 함수 strcpy(s, temp) 호출

Homework #1 Chapter 1 Chapter 2 Due: 3.30(월) 수업시간에 제출