유일한 개체들을 담는 자료구조를 모델링
집합을 집합 원소들의 정렬된 리스트로 표현
집합A에 대한 집합연산 : 를 만족해야 함.
이 연산은 파괴적일수도, 비파괴적일 수도 있음.
일반메소드
질의메소드
갱신메소드
예외
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct _Node {
struct _Node* prev;
struct _Node* next;
int elem;
} Node;
typedef struct _List {
struct _Node* H;
struct _Node* T;
} List;
Node* getNode() {
Node* n = (Node*)malloc(sizeof(Node));
n->prev = NULL;
n->next = NULL;
return n;
}
void putNode(Node* p) {
free(p);
}
List init() {
List L;
L.H = getNode();
L.T = getNode();
(L.H)->next = (L.T);
(L.T)->prev = (L.H);
return L;
}
void addLast(List L, int e) {
Node* T = L.T;
Node* n = getNode();
n->elem = e;
n->prev = T->prev;
n->next = T;
(T->prev)->next = n;
T->prev = n;
}
void removeFirst(List L) {
Node* H = L.H;
Node* newNext = (H->next)->next;
H->next = newNext;
newNext->prev = H;
}
int getFirst(List L) {
Node* H = L.H;
return (H->next)->elem;
}
bool isEmpty(List L) {
Node* H = L.H;
Node* T = L.T;
return (H->next == T) ? true : false;
}
Alg union(B)
input set A, set B
output set A∪B
1. C ← empty list
2. while( !(A.isEmpty()) & !(B.isEmpty()) )
a, b ← A.get(1), B.get(1)
if(a < b)
C.addLast(a)
A.removeFirst()
else if(a > b)
C.addLast(b)
B.removeFirst()
else
C.addLast(a)
A.removeFirst()
B.removeFirst()
3. while( !(A.isEmpty()) )
a ← A.get(1)
C.addLast(a)
A.removeFirst()
4. while( !(B.isEmpty()) )
b ← B.get(1)
C.addLast(b)
B.removeFirst()
5. return C
List Union_Destructive(List A, List B) {
List C = init();
while (!isEmpty(A) && !isEmpty(B)) {
int a = getFirst(A);
int b = getFirst(B);
if (a < b) {
addLast(C, a);
removeFirst(A);
} else if (a > b) {
addLast(C, b);
removeFirst(B);
} else {
addLast(C, a);
removeFirst(A);
removeFirst(B);
}
}
while (!isEmpty(A)) {
int a = getFirst(A);
addLast(C, a);
removeFirst(A);
}
while (!isEmpty(B)) {
int b = getFirst(B);
addLast(C, b);
removeFirst(B);
}
return C;
}
Alg union(B)
input set A, set B
output set A∪B
1. if((A=∅)&(B=∅))
return ∅
2. p ← getNode()
3. if(A=∅)
p.elem ← B.elem
p.next ← union(A, B.next)
else if(B=∅)
p.elem ← A.elem
p.next ← union(A.next, B)
else
P.elem ← A.elem
p.next ← union(A.next, B.next)
4. return p
Node* Union_Non_Destructive(Node* A, Node* B) {
if (A==NULL && B==NULL) {
return NULL;
}
Node* p = getNode();
if (A==NULL) {
p->elem = B->elem;
p->next = Union_Non_Destructive(A, B->next);
}
else if (B==NULL) {
p->elem = A->elem;
p->next = Union_Non_Destructive(A->next, B);
}
else {
p->elem = A->elem;
p->next = Union_Non_Destructive(A->next, B->next);
}
return p;
}
List Union_Non_Destructive_Caller(List A, List B) {
List C = init();
Node* head = Union_Non_Destructive((A.H)->next, (B.H)->next);
(C.H)->next = head;
Node* p = head;
while (p->next != NULL)
p = p->next;
(C.T)->prev = p;
return C;
}
Alg intersect(B)
input set A, set B
output set A∩B
1. C ← empty list
2. while( !(A.isEmpty()) & !(B.isEmpty()) )
a, b ← A.get(1), B.get(1)
if( a < b )
A.removeFirst()
else if ( a > b )
B.removeFirst()
else
C.addLast(a)
A.removeFirst()
B.removeFirst()
3. return C
List intersect_Destructive(List A, List B) {
List C = init();
while (!isEmpty(A) && !isEmpty(B)) {
int a = getFirst(A);
int b = getFirst(B);
if (a < b) {
removeFirst(A);
}
else if (a > b) {
removeFirst(B);
}
else {
addLast(C, a);
removeFirst(A);
removeFirst(B);
}
}
return C;
}
Alg intersect(B)
input set A, set B
output set A∩B
1. if( (A=∅)||(b=∅) )
return ∅
2. if(A.elem < B.elem)
return intersect(A.next, B)
else if(A.elem > B.elem)
return intersect(A, B.next)
else
p ← getNode()
p.elem = A.elem
p.next = intersect(A.next, B.next)
return p
Node* intersect_NonDestructive(Node* A, Node* B) {
if (A == NULL || B == NULL) {
return NULL;
}
while (1) {
int a = A->elem;
int b = B->elem;
if (a < b) {
return intersect_NonDestructive(A->next, B);
}
else if (a > b) {
return intersect_NonDestructive(A, B->next);
}
else {
Node* p = getNode();
p->elem = a;
p->next = intersect_NonDestructive(A->next, B->next);
return p;
}
}
}
List intersect_NonDestructive_caller(List A, List B) {
List C = init();
Node* head = intersect_NonDestructive((A.H)->next, (B.H)->next);
(C.H)->next = head;
Node* p = head;
while (p->next != NULL)
p = p->next;
(C.T)->prev = p;
return C;
}
Alg subtract(B)
input set A, set B
output set A-B
1. C ← empty list
2. while( !(A.isEmpty()) & !(B.isEmpty()) )
a, b ← A.get(1), B.get(1)
if( a < b )
C.addLast(a)
A.removeFirst()
else if( b > a )
B.removeFirst()
else
A.removeFirst()
B.removeFirst()
3. while( !(A.isEmpty()) )
a ← A.get(1)
C.addLast(a)
A.removeFirst()
4. return C
List subtract_Destructive(List A, List B) {
List C = init();
while (!isEmpty(A) && !isEmpty(B)) {
int a = getFirst(A);
int b = getFirst(B);
if (a < b) {
addLast(C, a);
removeFirst(A);
} else if (a > b) {
removeFirst(B);
} else {
removeFirst(A);
removeFirst(B);
}
}
while (!isEmpty(A)) {
int a = getFirst(A);
addLast(C, a);
removeFirst(A);
}
return C;
}
Alg subtract(B)
input set A, set B
output set A-B
1. if( (A=∅)&(B=∅) )
return ∅
else if(A=∅)
return ∅
else if(B=∅)
return A
2.
Alg member(e)
input set A, element e
output bool of e∈A
1. if(A=∅)
return True
2. p ← A
3. while(True)
a ← p.elem
if(e < a)
if(p.next = ∅)
return False
else
p ← p.next
else if(e > a)
return False
else
return True
bool member(List A, int e) {
if (isEmpty(A)) {
return false;
}
Node* p = (A.H)->next;
while (1) {
int a = p->elem;
if (e < a) {
if (p->next == NULL) {
return false;
}
else {
p = p->next;
}
}
else if (e > a) {
return false;
}
else {
return true;
}
}
}
Alg subset(B)
input set A, set B
output bool of A⊂B
1. if(A=∅)
return True
2. p ← A
3. while(True)
a ← p.elem
if(B.member(a))
if(p.next = ∅)
return True
else
p ← p.next
else
return False
bool subset(List A, List B) {
if (isEmpty(A) || isEmpty(B)) {
return false;
}
Node* p = (A.H)->next;
while (1) {
int a = p->elem;
if (member(B, a)) {
if (p->next == NULL) {
return true;
}
else {
p = p->next;
}
}
else {
return false;
}
}
}