C

[C] 집합 연산 함수 구현하기

migyul 2024. 10. 10. 03:55

집합에 원소를 추가하는 함수에 이어서

두 집합(배열)을 매개변수로 전달 받아 연산하는 함수를 구현하는 문제를 풀었다.

나는 아직 배열을 반환하는 법을 안 배워서, setResult라는 배열에 결과를 담아 그 크기를 반환하도록 구현하였다.

 

 

미리 만들어둔 hasElement, 집합이 특정 원소를 가지고 있는지 확인해주는 함수를 활용했다.

배열, 배열의 크기, 원소를 매개변수로 전달 받고

배열 안에 해당 원소가 존재하면 1, 아니면 0을 반환한다.

int hasElement(int set[], int size, int element)
{
	int i = 0;
	for (i = 0; i < size; i++)
		if (set[i] == element)
			return 1;

	return 0;
}

 

 

 

먼저 합집합 연산 함수이다.

 

hasElement 함수에 결과 배열과 그 크기, set1배열의 i번 인덱스값을 전달하였다.

합집합은 두 집합의 모든 원소를 중복없이 넣기만 하면 된다.

그래서 hasElement가 0을 반환했을 경우 => 아직 결과 배열에 존재하지 않는 원소

라고 생각하여 원소가 추가되도록 하였다.

hasElement가 1을 반환하면 이미 결과 배열에 존재하는 원소이기 때문에

중복인 원소는 추가되지 않는다.

 

여기서 cnt 변수에 setResult 배열의 크기를 담아 반환하는 것까지는 생각했는데,

처음에 원소를 담을 때 아무생각없이 i번 인덱스에 담아버려서 오류가 많이 났다.

중복일 경우, 원소가 추가되지 않기 때문에 인덱스 번호를 증가시키면 안 되는데

i를 사용하니 size 배열의 위치를 따라가기 때문이다.

원소가 추가되지 않으면 인덱스 번호도 그대로이기 때문에 cnt번 인덱스에 원소를 담아야 한다.

 

합집합은 set1, set2 모두 확인하고 추가해야 하기 때문에 2개의 반복문으로 처리했다. 

int setUnion(int set1[], int size1, int set2[], int size2, int setResult[])
{
	int i;
	int cnt = 0;

	for (i = 0; i < size1; i++) {
			if (!hasElement(setResult, cnt, set1[i])) {
				setResult[cnt] = set1[i];
				cnt++;
			}
		}
	
	for (i = 0; i < size2; i++) {
			if (!hasElement(setResult, cnt, set2[i])) {
				setResult[cnt] = set2[i];
				cnt++;
			}
		}

	return cnt;
}

 

 

 

다음은 교집합이다.

 

교집합은 한 집합을 기준으로 특정 원소를 다른 집합도 가지고 있는지만 확인하면 되기 때문에

비교적 코드가 더 간결하다.

set1 집합을 기준으로 hasElement에 set2 배열과 크기, set1의 i번 인덱스 원소를 매개변수로 전달한다.

1이 반환되면 => set1의 원소를 set2도 가지고 있다

는 뜻이기 때문에 setResult 배열의 cnt번 인덱스에 원소를 추가하도록 하였다.

int setIntersection(int set1[], int size1, int set2[], int size2, int setResult[])
{
	int i;
	int cnt = 0;

		for (i = 0; i < size1; i++) {
			if (hasElement(set2, size2, set1[i])) {
				setResult[cnt] = set1[i];
				cnt++;
			}
		}

	return cnt;
}

 

 

 

마지막 차집합이다.

 

역시 hasElement 함수를 이용했다.

set1 집합을 기준으로 set2를 전달하고,

hasElement가 0을 반환하면 => set1의 i번 인덱스 원소를 set2가 가지고 있지 않다

그러면 차집합 연산에 의해 사라지지 않는 원소이기 때문에 setResult에 추가되도록 했다.

 

차집합이기 때문에 set1이 set2보다 크기가 크다는 전제로 하는 줄 알았는데,

코드 리뷰를 하다보니 길이는 상관없다는 것을 알았다.

어차피 hasElement에서 size2만큼 반복문을 돌려서 이 원소가 있는지 없는지 확인하기 때문에

set2의 크기가 커져도 상관이 없는 것이다.

int setComplements(int set1[], int size1, int set2[], int size2, int setResult[])
{
	int i;
	int cnt = 0;

	for (i = 0; i < size1; i++) {
		if (!hasElement(set2, size2, set1[i])) {
			setResult[cnt] = set1[i];
			cnt++;
		}
	}

	return cnt;
}

 

 

 

교집합과 차집합은 쉽게 풀렸지만, 합집합이 조금 헷갈렸다.
코드를 다시 보며 생각하니 알게 되는 것들이 많았다.
인덱스에 습관처럼 i나 j 넣지 않도록 조심하고 한 번 더 생각해야겠다!!