교수님이 쓰라고 하셔서 쓰는 그런데 은근 재밌는 듯

자료구조

[자료구조] 중간고사 대비

shinyunha 2025. 10. 26. 17:22

알고리즘

Correctness: 정답에 얼마나 근접한가
Presicion: 넣는 input이 달라져도 correctness는 같은가
Determinism: 같은 input을 넣으면 항상 같은 output이 나오는가


자료형

boolean 1 byte
char 1 byte
short 2 bytes
int 4 bytes
float 4 bytes
double 8 bytes
pointer 4 bytes or 8 bytes

 

사용자 정의 자료형

struct: 다른 타입의 데이터를 하나로 묶기
union: 자료를 동시에 사용하지 않을 때 (가장 큰 자료형 만큼만 메모리 사용)
enum: 상수에 이름 붙인 거


빅오표기법


Divide Conquer(Recursive): 큰 문제를 쪼개서 해결, 쪼개진 문제는 독립된 문제로 여김 (여러개의 프로세서)
Dynamic Programming(Iterative): Logic이 항상 같음 (하나의 프로세서)


x^n 계산

반복적 방법1 - O(n)

double slow_power(double x, int n){
    double result = 1.0;
    
    for(int i = 0; i < n; i++) //그냥 x를 n번 Iterative하게 곱하기
        result = result * x;
        
    return result;
}

순환적 방법 - O(logn)

double power(double x, int n){
    if(n==0) return 1;
    else if((n%2)==0) //n이 짝수면
        return power(x*x, n/2) //recursive
    else //n이 홀수면
        return x*power(x*x, (n-1)/2); //recursive
}

반복적 방법2 - O(logn)

exp_via_repeated_squaring(x,n){
    result = 1;
    a = x;
    
    while(n > 0){
        if(n mod 2 == 1) //이진수로 표현할 때 1인 경우에만 곱하기
            result = result * a
            
        a = a * a //x, x^2, x^4, x^8, x^16 ... 으로 변화
        n = n/2의 내림
    }
    
    return result;
}

피보나치

순환적 방법 - O(2^n)

int fib(int n){
    if(n==0) return 0;
    if(n==1) return 1;
    
    return (fib(n-1)+fib(n-2)); //recursive
}

같은 항이 중복해서 계산됨 반반

반복적 방법

int fib_iter(int n){
    if(n==0) return 0;
    if(n==1) return 1;
    
    int pp = 0;
    int p = 1;
    int result = 0;
    
    for(int i = 2; i <= n; i++){
        result = p + pp; //f(n) = f(n-1) + f(n-2)
        pp = p; //f(n-2)
        p = result; //f(n-1)
    }
    return result;
}

하노이 탑

f(n-1) * 2 + 1

//from에 쌓여있는 n개의 원판을 tmp를 사용하여 to로 옮기기
void hanoi_tower(int n, char from, char tmp, char to){ 
    if(n==1) printf("원판을 %c에서 %c로 옮긴다", from, to);
    else{
        hanoi_tower(n-1, from, to, tmp); //n-1개를 from에서 tmp로 옮기기
        printf("원판 %d을 %c에서 %c로 옮긴다", n, from, to); //가장 큰 원판 하나 옮기기
        hanoi_tower(n-1, tmp, from, to); //n-1개를 tmp에서 to로 옮기기
    }
}

 


Head recursion: fact(n) = fact(n-1) * n
Tail recursion: fact(n) = n * fact(n-1)
 
메모리 효용성 때문에 tail이 더 좋다(push 후에 바로 pop)


배열과 다항식

모든 항을 배열에 저장

#define MAX_DEGREE 101

typedef struct {
	int degree;
	float coef[MAX_DEGREE];
}polynomial;

polynomial a = { 5, {10, 0, 0, 0, 6, 3 } }; //차수 큰 것부터 저장
polynomial poly_add1(polynomial A, polynomial B) {
	polynomial C; //결과 다항식
	int Apos = 0, Bpos = 0, Cpos = 0; //배열 인덱스

	//지금 보고 있는 항 차수, 최대차항에서 출발
	int degree_a = A.degree; 
	int degree_b = B.degree;

	C.degree = MAX(A.degree, B.degree); //결과 다항식 차수

	while (Apos < A.degree && Bpos < B.degree) {
		if (degree_a > degree_b) { //A항 > B항 
			C.coef[Cpos++] = A.coef[Apos++];
			degree_a--;
		}
		else if (degree_a == degree_b) { //A항 == B항 
			C.coef[Cpos++] = A.coef[Apos++] + B.coef[Bpos++];
			degree_a--;
			degree_b--;
		}
		else //B항 > A항 
		{
			C.coef[Cpos++] = B.coef[Bpos++];
			degree_b--;
		}
	}
	return C;
}

 

0이 아닌 항만 배열에 저장

#define MAX_TERMS 101

struct{
    float coef;
    int expon;
}terms[MAX_TERMS];

int avail;
//C = A + B
//compare: 두 정수 비교하여 >,=,< 반환
//attach: avail 위치에 새로운 항 추가

poly_add2(int As, int Ae, int Bs, int Be, int *Cs, int *Ce){
    float tempcoef;
    *Cs = avail; //C를 저장할 시작 주소
    
    while(As <= Ae && Bs <= Be){
        switch(compare(terms[As].expon, terms[Bs].expon)){ 
            case'>': //A의 차수 > B의 차수
                attach(terms[As].coef, terms[As].expon); 
                As++;
                break;
            case'=': //A의 차수 == B의 차수
                tempcoef = terms[As].coef + terms[Bs].coef;
                if(tempcoef) attach(tempcoef, terms[As].expon); //0이 아닐 때
                As++;
                Bs++;
                break;
            case'<': //A의 차수 < B의 차수
                attach(terms[Bs].coef, terms[Bs].expon); 
                Bs++;
                break;
        }
    }
    
    for(As <= Ae; As++){ //B가 먼저 끝나면 A의 나머지 항들을 이동
        attach(terms[As].coef, terms[As]);
    }
    for(Bs <= Be; Bs++){ //A가 먼저 끝나면 B의 나머지 항들을 이동
        attach(terms[Bs].coef, terms[Bs]);
    }
    
    *Ce = avail -1;
}

희소행렬

대부분의 항들이 0인 배열
 

2차원 배열을 이용하여 배열의 전체 요소 저장

#define ROWS 3
#define COLS 3

void matrix_transpose(int A[ROWS][COLS], int B[ROWS][COLS]){
    for(int r = 0; r < ROWS; r++)
        for(int c = 0; c < COLS; c++)
            B[c][r] = A[r][c];
}

0이 아닌 요소들만 저장

typedef struct{
    int row;
    int col;
    int value;
}element;

typedef struct SparseMatrix{
    element data[MAX_TERMS];
    int rows; //행의 개수
    int cols; //열의 개수
    int terms; //항의 개수
}SparseMatrix;
SparseMatrix matrix_transpose2(SparseMatrix a){
    SparseMatrix b;
    int Bindex;
    
    b.rows = a.cols;
    b.cols = a.rows;
    b.terms = a.terms;
    
    if(a.terms > 0){
        Bindex = 0;
        //col기준으로 한 줄씩 term 있는지 확인하여 저장
        for(int c = 0; c < a.cols; c++){  
            for(int i = 0; i < a.terms; i++){ 
                if(a.data[i].col == c){ 
                    b.data[Bindex].row = a.data[i].col; 
                    b.data[Bindex].col = a.data[i].row; 
                    b.data[Bindex].value = a.data[i].value; 
                    Bindex++; 
                } 
            } 
        } 
    } 
    return b;
}

동적메모리 할당을 하면 heap에 저장됨


https://shinyunha.tistory.com/4

 

[자료구조] 스택

LIFO: Last-in First-out먼저 연산하고 싶은 것을 나중에 삽입스택 ADT(추상데이터타입)create(size)크기 size인 공백 스택 생성size(s)스택의 크기 리턴is_full(s)스택의 원소수가 size와 같으면 TRUEis_empty(s)스택

shinyunha.tistory.com

https://shinyunha.tistory.com/6

 

[자료구조] 큐

FIFO: First-In First-Out왼쪽 끝에서 삭제 오른쪽 끝에서 삽입 front: 가장 최근에 삭제된 데이터의 indexrear: 가장 최근에 삽입된 데이터의 index초기값은 둘 다 -1 모든 연산에 대한 시간 복잡도: O(1) 액션

shinyunha.tistory.com

 https://shinyunha.tistory.com/m/12

 

[자료구조] 연결리스트

단순 연결리스트시간 복잡도O(n) 또는 O(1) 장점: 자투리 메모리 공간 사용 단점: 포인터 변수가 메모리를 차지함 배열에서 삽입연산을 하려면 다 뒤로 옮겨줘야함삭제연산을 하려면 다 앞으로 옮

shinyunha.tistory.com

https://shinyunha.tistory.com/13

 

[자료구조] 트리

계층적 자료구조 edge(간선): 노드와 노드 사이 연결node: 자료가 저장된 구조체 root node: 부모가 없는 최상위 조상 노드parent/child node: 하나의 간선으로 직접 연결된 상위/하위 계층 노드ancestor/descend

shinyunha.tistory.com

https://shinyunha.tistory.com/14

 

[자료구조] Heap

우선순위 큐저장순서에 상관없이 우선순위로 뽑아냄delete(q)우선순위가 가장 높은 요소 삭제find(q)우선순위가 가장 높은 요소 반환 최소 우선순위 큐(min heap): 값이 작은 노드가 우선순위가 높다

shinyunha.tistory.com

 

'자료구조' 카테고리의 다른 글

[자료구조] 트리  (0) 2025.10.27
[자료구조] 연결리스트  (0) 2025.10.26
[자료구조] 큐  (0) 2025.09.30
[자료구조] 배열 - 다항식 더하기  (0) 2025.09.27
[자료구조] 스택  (0) 2025.09.25