자료구조

chapter 2-1(POLYNOMIAL) : 배열, 구조체, 포인터

kangyuseok 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);
}