ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • chapter 2-1(POLYNOMIAL) : 배열, 구조체, 포인터
    자료구조 2021. 9. 27. 15:26
    728x90

    2차원 배열 동적 할당

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int main() {
    	int** x; //이중 포인터
    	int rows; //행
    	int cols; //열
    	scanf("%d", &rows);
    	x = (int**)malloc(rows * sizeof(int*)); //행을 동적할당
    	scanf("%d", &cols);
    	for (int i = 0; i < rows; i++) {
    		x[i] = (int*)malloc(cols * sizeof(int)); //행마다 열의 크기만큼 동적할당
    	}
    
    	for (int i = 0; i < rows; i++) {
    		for (int j = 0; j < cols; j++) {
    			scanf("%d", &x[i][j]);
    		}
    	}
    	for (int i = 0; i < rows; i++) {
    		for (int j = 0; j < cols; j++) {
    			printf("%d ", x[i][j]);
    		}
    		printf("\n");
    	}
    	return 0;
    }

     

    POLYNOMIAL (다항식 배열)

    다항식의 계산을 배열을 이용하여 계산하는 것 입니다. 

    먼저 다항식을 배열에 저장하여야 합니다.

    예를 들어 10x^5+6x^1+3은

    10 0 0 0 6 3

    이렇게 배열에 저장됩니다. 우리는 이러한 배열의 이름을 coef 라고 합시다.

    이것을 코드로 구현하면

    #define MAX_DEGREE 101 //다항식의 최대차수 +1
    typedef struct {
    	int degree; //최고차항의 차수
    	float coef[MAX_DEGREE]; 
    }polynominal;
    
    polynominal a = { 5,{10,0,0,0,6,3} };

    구조체를 이용하여 변수 degree에는 다항식의 최대차항의 차수가 들어갑니다. 

    coef 배열을 이용하여 계수를 저장할 것입니다.

    이를 polynominal이라는 구조체 변수에 저장합니다.

    이제 다항식의 덧셈을 함수로 구현하였습니다.

    polynominal poly_add1(polynominal A, polynominal B) {
    	polynominal 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);

    변수 Apos는 구조체 polynominal A의 coef배열의 인덱스 번호 를 가리키는 변수입니다. 따라서 배열의 첫번째인 0으로 초기화 해줍니다.

    나머지 배열도 마찬가지로 초기화 해줍니다. 

    polynominal C는 A와B를 계산한 값이 C로 들어가게 됩니다.

    degree_a라는 변수는 A의 최대차항의 계수입니다. 

    다항식의 계산은 먼저 최대차항의 차수를 비교하므로 비교가 끝나면 다음 차수로 넘어가야 하기 때문에

    계산이 끝날때 마다 degree_a의 수를 1씩 빼줍니다.

    C.degree는 A와B의 최대차항의 계수중 큰 수가 들어갑니다.

    x^5와 x^4를 더하면 x^5+x^4가 되는데 당연히 최대차항은 5이므로 둘중 최대차항이 큰 수가 C에 들어갑니다.

    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 { //A항의 차수 < B항의 차수
    			C.coef[Cpos++] = B.coef[Bpos++];
    			degree_b--;
    		}
    	}
    	return C;
    }

    while절 안에서 A와 B의 최대차항을 비교해줍니다

    while절을 모두 수행하면 구조체 C를 return해줍니다.

    void print_poly(polynominal p) {
    	for (int i = p.degree; i > 0; i--) {
    		if (p.coef[p.degree - i] == 0) //계수가 0이면 출력안함
    			continue;
    		printf("%3.1fx^%d + ", p.coef[p.degree - i], i);
    	}
    	printf("%3.1f\n", p.coef[p.degree]);
    }

    구조체 출력부분입니다. 

    계수가 0인 부분은 출력해주지 않았습니다.


    전체코드입니다.

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define MAX(a,b) (a>b ? a:b)
    #define MAX_DEGREE 101 //다항식의 최대차수 +1
    typedef struct {
    	int degree; //최고차항의 차수
    	float coef[MAX_DEGREE]; 
    }polynominal;
    polynominal poly_add1(polynominal A, polynominal B);
    void print_poly(polynominal p);
    int main() {
    	polynominal a = { 5,{3,6,0,0,0,10} };
    	polynominal b = { 4,{7,0,5,0,1} };
    	polynominal c;
    
    	print_poly(a);
    	print_poly(b);
    	c = poly_add1(a, b);
    	printf("--------------------------------------------\n");
    	print_poly(c);
    	return 0;
    }
    // C는 A+B 여기서 A와 B는 다항식이다. 구조체가 반환된다.
    polynominal poly_add1(polynominal A, polynominal B) {
    	polynominal 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 { //A항의 차수 < B항의 차수
    			C.coef[Cpos++] = B.coef[Bpos++];
    			degree_b--;
    		}
    	}
    	return C;
    }
    void print_poly(polynominal p) {
    	for (int i = p.degree; i > 0; i--) {
    		if (p.coef[p.degree - i] == 0) //계수가 0이면 출력안함
    			continue;
    		printf("%3.1fx^%d + ", p.coef[p.degree - i], i);
    	}
    	printf("%3.1f\n", p.coef[p.degree]);
    }


    그러나 이러한 방법에는 메모리의 제한이 생긴다는 단점이 있습니다.

    예를 들어 x^1000+1의 경우 배열의 칸을 1000개 이상의 메모리를 설정해야합니다.

    따라서 계수가 0인 항들은 아예 배열에 저장하지 않아야 메모리를 절약할 수 있습니다.

    예를 들어 10x^5+6x+3 의 경우 ((10, 5), (6, 1),(3, 0))이렇게 배열에 저장 가능합니다.

    #define MAX_TERMS 101
    struct{
        float coef; //계수
        int expn; //차수
    }terms[MAX_TERMS];
    int avail;

    A = 8x^3 + 7x + 1

    B =10x^3 + 3x^2 + 1

    avail 변수는 현재 비어있는 요소의 인덱스를 가리킵니다. 여기서 avail은 6이 됩니다.

          A                                    B                                     avail

          0           1            2          3             4          5             6

    8 7 1 10 3 1        
    3 1 0 3 2 0        

    하지만 이러한 방법에도 단점이 존재합니다.

    예외의 다항식에 대해서는 1번쨰 방법보다 더 많은 메모리를 사용할 수 도 있습니다.

    다항식의 차수도 배열로 저장해야하기 떄문입니다.

    계산이 다된 계수와 차수는 avail자리에 들어가고 다시 avail+1해주면 됩니다. 

    마지막으로 어느한쪽의 다항식이 계산이 끝날때 까지 poly_add2 함수를 반복해주면 됩니다.

    char compare(int a, int b) {
    	if (a > b)return '>';
    	else if (a == b)return '=';
    	else return '<';
    }

    차수를 비교해주는 함수입니다. 

    void attach(float coef, int expon) {
    	if (avail > MAX_TERMS) { //배열의 크기가 너무 커질때
    		fprintf(stderr, "항의 개수가 너무 많음");
    		exit(1);
    	}
    	terms[avail].coef = coef;
    	terms[avail].expon = expon;
    	avail++; //삽입이 끝난후 avail을 1을 늘려준다(다음 데이터가 들어올수 있게)
    }

    계산된 수를 배열에 삽입해주는 함수 입니다.

    void poly_add2(int AS, int AE, int BS, int BE, int* CS, int* CE) {
    	float tempcoef; //두 다항식의 계수 합을 저장할 변수
    	*CS = avail;
    	while (AS <= AE && BS <= BE) 
    		switch (compare(terms[AS].expon, terms[BS].expon)) {
    		case '>': //A의 차수 > B의 차수
    			attatch(terms[AS].coef, terms[AS].expon);
    			AS++;
    			break;
    		case '=': //A의 차수 = B의 차수
    			tempcoef = terms[AS].coef + terms[BS].coef;
    			if (tempcoef) //두 계수의 합이 0이 아닐때
    				attatch(tempcoef, terms[AS].expon);
    			AS++; BS++;
    			break;
    		case '<': //A의 차수 < B의 차수
    			attatch(terms[BS].coef, terms[BS].expon);
    			BS++;
    			break;
    		}
    	for (; AS <= AE; AS++)  //A의 나머지 항들을 이동
    		attatch(terms[AS].coef, terms[AS].expon);
    	for (; BS <= BE; BS++) //B의 나머지 항들을 이동
    		attatch(terms[BS].coef, terms[BS].expon);
    	*CE = avail - 1;
    }

    계산 부분입니다.

    변수 AS와 AE는 다항식 A의 처음과 마지막을 카리키고 BS와 BE는 다항식 B의 처음과 끝을 가리킵니다.

    CS와 CE는 덧셈의 결과로 생성되는 다항식의 처음과 끝을 가리킵니다.

    void print_poly(int s, int e) {
    	for (int i = s; i < e; i++) 
    		printf("%3.1fx^%d + ", terms[i].coef, terms[i].expon);
    	printf("%3.1fx^%d\n", terms[e].coef, terms[e].expon);
    }

    출력 부분입니다.


    전체코드입니다.

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define MAX_TERMS 101 //다항식의 최대차수 +1
    typedef struct {
    	float coef; //계수
    	int expon;  //차수
    }polynomial;
    polynomial terms[MAX_TERMS] = { {8,3},{7,1},{1,0},{10,3},{3,2},{1,0} };
    int avail = 6;
    char compare(int a, int b);
    void attach(float coef, int expon);
    void poly_add2(int AS, int AE, int BS, int BE, int* CS, int* CE);
    void print_poly(int s, int e);
    int main() {
    	int AS = 0, AE = 2, BS = 3, BE = 5, CS, CE;
    	poly_add2(AS, AE, BS, BE, &CS, &CE);
    	print_poly(AS, AE);
    	print_poly(BS, BE);
    	printf("---------------------------------------------\n");
    	print_poly(CS, CE);
    	return 0;
    }
    char compare(int a, int b) {
    	if (a > b)return '>';
    	else if (a == b)return '=';
    	else return '<';
    }
    void attach(float coef, int expon) {
    	if (avail > MAX_TERMS) { //배열의 크기가 너무 커질때
    		fprintf(stderr, "항의 개수가 너무 많음");
    		exit(1);
    	}
    	terms[avail].coef = coef;
    	terms[avail].expon = expon;
    	avail++; //삽입이 끝난후 avail을 1을 늘려준다(다음 데이터가 들어올수 있게)
    }
    void poly_add2(int AS, int AE, int BS, int BE, int* CS, int* CE) {
    	float tempcoef; //두 다항식의 계수 합을 저장할 변수
    	*CS = avail;
    	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) //두 계수의 합이 0이 아닐때
    				attach(tempcoef, terms[AS].expon);
    			AS++; BS++;
    			break;
    		case '<': //A의 차수 < B의 차수
    			attach(terms[BS].coef, terms[BS].expon);
    			BS++;
    			break;
    		}
    	for (; AS <= AE; AS++)  //A의 나머지 항들을 이동
    		attach(terms[AS].coef, terms[AS].expon);
    	for (; BS <= BE; BS++) //B의 나머지 항들을 이동
    		attach(terms[BS].coef, terms[BS].expon);
    	*CE = avail - 1;
    }
    void print_poly(int s, int e) {
    	for (int i = s; i < e; i++) 
    		printf("%3.1fx^%d + ", terms[i].coef, terms[i].expon);
    	printf("%3.1fx^%d\n", terms[e].coef, terms[e].expon);
    }

     

Designed by Tistory.