본문 바로가기
알고리즘/자료구조(C)

배열로 집합 만들기

by 진진리 2023. 9. 23.
728x90
  • 구조체 IntSet: int형 원소를 갖는 집합을 관리
typedef struc{
    int max; //집합의 최대 크기
    int num; //집합의 원소 개수
    int* set; //집합
} IntSet;

 

  • 헤더 파일 IntSet.h
#ifndef ___IntSet
#define ___IntSet

typedef struct {
	int max;	
	int num;	
	int *set;	
} IntSet;

int Initialize(IntSet *s, int max);

int IsMember(const IntSet *s, int n);

int IsFull(const IntSet *s);

void Add(IntSet *s, int n);

void Remove(IntSet *s, int n);

int Capacity(const IntSet *s);

int Size(const IntSet *s);

void Assign(IntSet *s1, const IntSet *s2);

int Equal(const IntSet *s1, const IntSet *s2);

IntSet *Union(IntSet *s1, const IntSet *s2, const IntSet *s3);

IntSet *Intersection(IntSet *s1, const IntSet *s2, const IntSet *s3);

IntSet *Difference(IntSet *s1, const IntSet *s2, const IntSet *s3);

IntSet *SymmetricDifference(IntSet *s1, const IntSet *s2, const IntSet *s3);

IntSet *ToUnion(IntSet *s1, const IntSet *s2);

IntSet *ToIntersection(IntSet *s1, const IntSet *s2);

IntSet *ToDifference(IntSet *s1, const IntSet *s2);

int IsSubset(const IntSet *s1, const IntSet *s2);

int IsProperSubset(const IntSet *s1, const IntSet *s2);

void Print(const IntSet *s);

void PrintLn(const IntSet *s);

void Clear(IntSet *s);

void Terminate(IntSet *s);

#endif

 

 

  • 소스파일 IntSet.c
#include <stdio.h>
#include <stdlib.h>
#include "IntSet.h"

int Initialize(IntSet* s, int max) {
	s->num = 0;
	if ((s->set = calloc(max, sizeof(int))) == NULL) {
		s->max = 0;
		return -1;
	}
	s->max = max;
	return 0;
}

int IsMember(const IntSet* s, int n){
	int i;
	for (i = 0; i < s->num; i++)
		if (s->set[i] == n) return i;
	return -1;
}

int IsFull(const IntSet* s) {
	return s->num >= s->max;
}

void Add(IntSet* s, int n) {
	if (s->num < s->max && IsMember(s, n) == -1) {
		s->set[s->num++] = n;
	}
}

void Remove(IntSet* s, int n) {
	int idx;
	if ((idx = IsMember(s, n)) != -1) {
		s->set[idx] = s->set[--s->num]; //마지막 요소를 삭제 위치로 옮김
	}
}

int Capacity(const IntSet* s) {
	return s->max;
}

int Size(const IntSet* s) {
	return s->num;
}

void Assign(IntSet* s1, const IntSet* s2) { //집합 s2를 s1에 복사
	int i;
	int n = (s1->max < s2->num) ? s1->max : s2->num;
	for (i = 0; i < n; i++)
		s1->set[i] = s2->set[i];
	s1->num = n;
}

int Equal(const IntSet* s1, const IntSet* s2) {
	int i, j;
	if (Size(s1) != Size(s2)) return 0;
	for (i = 0; i < s1->num; i++) {
		for (j = 0; j < s2->num; j++) 
			if (s1->set[i] == s2->set[j]) break; //s2에서 같은 요소를 찾으면 나감
		if (j == s2->num) return 0; //s2에서 같은 요소를 끝까지 찾지 못하면 false(0)
	}
	return 1;
}

IntSet* Union(IntSet* s1, const IntSet* s2, const IntSet* s3) { //s2와 x3의 합집합을 s1에 대입
	int i;
	Assign(s1, s2);
	for (i = 0; i < s3->num; i++) {
		Add(s1, s3->set[i]);
	}
	return s1;
}

IntSet* Intersection(IntSet* s1, const IntSet* s2, const IntSet* s3) { //교집합
	int i, j;
	s1->num = 0;
	for (i = 0; i < s2->num; i++)
		for (j = 0; j < s3->num; j++)
			if (s2->set[i] == s3->set[j])
				Add(s1, s2->set[i]);
	return s1;
}

IntSet* Difference(IntSet* s1, const IntSet* s2, const IntSet* s3) { //s1=s2-s3 차집합
	int i, j;
	s1->num = 0;
	for (i = 0; i < s2->num; i++) {
		for (j = 0; j < s3->num; j++)
			if (s2->set[i] == s3->set[j]) break;
		if (j == s3->num) Add(s1, s2->set[i]);
	}
	return s1;
}

IntSet* SymmetricDifference(IntSet* s1, const IntSet* s2, const IntSet* s3) { //대칭차
	int i;

	s1->num = 0;

	for (i = 0; i < s2->num; i++)
		if (IsMember(s3, s2->set[i]) == -1)
			Add(s1, s2->set[i]);

	for (i = 0; i < s3->num; i++)
		if (IsMember(s2, s3->set[i]) == -1)
			Add(s1, s3->set[i]);

	return s1;
}

IntSet *ToUnion(IntSet *s1, const IntSet *s2){ //s1에 s2의 원소를 추가
	int i;

	for (i = 0; i < s2->num; i++)
		Add(s1, s2->set[i]);

	return s1;
}

IntSet *ToIntersection(IntSet *s1, const IntSet *s2){ //s1에서 s2에 없는 원소를 삭제
	int i = 0;

	while (i < s1->num) {
		if (IsMember(s2, s1->set[i]) == -1)
			Remove(s1, s1->set[i]);
		else
			i++;
	}
	return s1;
}

IntSet *ToDifference(IntSet *s1, const IntSet *s2){ //s1에서 s2에 있는 원소를 삭제
	int i;

	for (i = 0; i < s2->num; i++)
		Remove(s1, s2->set[i]);

	return s1;
}

int IsSubset(const IntSet *s1, const IntSet *s2){ //s1이 s2의 부분집합이면 1 아니면 0 반환
	int i, j;

	for (i = 0; i < s1->num; i++) {
		for (j = 0; j < s2->num; j++)
			if (s1->set[i] == s2->set[j])
				break;
		if (j == s2->num)					
			return 0;
	}
	return 1;
}

int IsProperSubset(const IntSet *s1, const IntSet *s2){ //s1이 s2의 진부분집합이면 1 아니면 0 반환
	int i;

	if (s1->num >= s2->num)					
		return 0;							

	return IsSubset(s1, s2);
}

void Print(const IntSet* s) {
	int i;
	printf("{ ");
	for (i = 0; i < s->num; i++)
		printf("%d ", s->set[i]);
	printf("}");
}

void PrintLn(const IntSet* s) { // 줄바꿈 문자 포함
	Print(s);
	putchar('\n');
}

void Clear(IntSet *s){ //s의 모든 원소를 삭제
	s->num = 0;
}

void Terminate(IntSet* s) {
	if (s->set != NULL) {
		free(s->set);
		s->max = s->num = 0;
	}
}

 

 

  • IntSet을 사용하는 프로그램 IntSetTest.c
#include <stdio.h>
#include "IntSet.h"

enum {ADD, RMV, SCH};

int scan_data(int sw) {
	int data;
	switch (sw) {
	case ADD: printf("추가할 데이터 : "); break;
	case RMV: printf("삭제할 데이터 : "); break;
	case SCH: printf("검색할 데이터 : "); break;
	}
	scanf_s("%d", &data);

	return data;
}

int main(void) {
	IntSet s1, s2, temp;
	Initialize(&s1, 512); Initialize(&s2, 512); Initialize(&temp, 512);

	while (1) {
		int m, x, idx;

		printf("s1 = "); PrintLn(&s1);
		printf("s2 = "); PrintLn(&s2);
		printf("(1)s1에 추가 (2)s1에서 삭제 (3)s1에서 검색 (4)s1<-s2 (5)여러 연산\n"
			"(6)s2에 추가 (7)s2에서 삭제 (8)s2에서 검색 (9)s2<-s1 (0)종료 : ");

		scanf_s("%d", &m);
		if (m == 0) break;

		switch (m) {
		case 1: x = scan_data(ADD); Add(&s1, x); break;
		case 2: x = scan_data(RMV); Remove(&s1, x); break;
		case 3: x = scan_data(SCH); idx = IsMember(&s1, x); 
			printf("s1에 들어있%s.\n", idx >= 0 ? "습니다" : "지 않습니다");  break;
		case 4: Assign(&s1, &s2); break;
		case 5: printf("s1 == s2 = %s\n", Equal(&s1, &s2) ? "true" : "false");
			printf("s1 & s2 ="); Intersection(&temp, &s1, &s2);
			PrintLn(&temp);
			printf("s1 | s2 ="); Union(&temp, &s1, &s2);
			PrintLn(&temp);
			printf("s1 - s2 ="); Difference(&temp, &s1, &s2);
			PrintLn(&temp);
			break;
		case 6: x = scan_data(ADD); Add(&s2, x); break;
		case 7: x = scan_data(RMV); Remove(&s2, x); break;
		case 8: x = scan_data(SCH); idx = IsMember(&s2, x);
			printf("s2에 들어있%s.\n", idx >= 0 ? "습니다" : "지 않습니다");  break;
		case 9: Assign(&s2, &s1); break;
		}
	}
	Terminate(&s1); Terminate(&s2); Terminate(&temp);

	return 0;
}

'알고리즘 > 자료구조(C)' 카테고리의 다른 글

문자열 검색: 브루트-포스법(Brute force method)  (0) 2023.09.23
비트 벡터로 집합 만들기  (0) 2023.09.23
힙 정렬(Heap Sort)  (0) 2023.09.22
병합 정렬(Merge Sort)  (0) 2023.09.22
퀵 정렬(Quick Sort)  (0) 2023.09.22