Pers.narod.ru. Алгоритмы. Объединение, пересечение и разность множеств, реализация через массивы |
Объединением множеств A и B называется множество элементов, принадлежащих,
по крайней мере, одному из данных множеств (т. е. либо A, либо B, либо
одновременно и A и B). Эту операцию обозначают A∪B
и читают "объединение A и B".
Пересечением множеств A и B называется множество элементов,
принадлежащих одновременно и A и B. Обозначают A∩B
и читают
"пересечение A и B".
Разностью множеств A и B называется множество элементов,
принадлежащих A и не принадлежащих B. Обозначают A\B
и читают "разность A и B".
Прилагаемая ниже программа реализует множества как статические массивы языка Си и содержит функции для выполнения указанных операций над массивами. Функции возвращают указатели на новый массив, который формируется динамически и является результатом операции. Предварительно из массивов удаляются одинаковые элементы, если они там есть.
#include <stdio.h> #include <alloc.h> void delete_equal (int *n0, int *a) { //Удаляет из массива повторяющиеся элементы и вычисляет новую размерность n0 int n=*n0; int i=0; while (i<n) { int j=i+1; while (j<n) { if (a[i]==a[j]) { for (int k=j; k<n-1; k++) a[k]=a[k+1]; n--; } else j++; } i++; } *n0=n; } int find_item(int na,int *a,int b) { //Ищет элемент b в массиве a[na] и возвращает его индекс или -1 (не найдено) for (int i=0; i<na; i++) if (a[i]==b) return i; return -1; } int *copy_array (int n, int *a, int *c) { //Копирует массив a в новый массив c и возвращает указатель на него c=(int *)calloc (n,sizeof(int)); if (c==NULL) return NULL; for (int i=0; i<n; i++) c[i]=a[i]; return &c[0]; } int *union_array (int na, int *a, int nb, int *b, int *nc) { //Объединение массивов a и b с размерностями na и nb //в новый динамический массив (в массив войдут уникальные элементы, //присутствующие хотя бы в одном из массивов a,b) int *c,i,j; if (na<1) { if (nb<1) return NULL; else { delete_equal (&nb,b); return copy_array (nb,b,c); } } else if (nb<1) { delete_equal (&na,a); return copy_array (na,a,c); } delete_equal(&na,a); delete_equal(&nb,b); //Вычисляем количество разных элементов в 2 массивах int kc=0; for (i=0; i<na; i++) if (find_item(nb,b,a[i])!=-1) kc++; *nc=na+nb-kc; c=(int *)calloc (*nc,sizeof(int)); if (c==NULL) return NULL; //Формируем массив c int k=0; for (i=0; i<na; i++) c[k++]=a[i]; for (j=0; j<nb; j++) if (find_item(na,a,b[j])==-1) c[k++]=b[j]; return c; } int *cross_array (int na, int *a, int nb, int *b, int *nc) { //Пересечение массивов a и b с размерностями na и nb //в новый динамический массив (в массив войдут уникальные элементы, //присутствующие в каждом из массивов a,b) int *c,i,j; if (na<1 || nb<1) return NULL; delete_equal(&na,a); delete_equal(&nb,b); //Вычисляем количество одинаковых элементов в 2 массивах *nc=0; for (i=0; i<na; i++) if (find_item(nb,b,a[i])!=-1) (*nc)++; c=(int *)calloc (*nc,sizeof(int)); if (c==NULL) return NULL; //Формируем массив c int k=0; for (i=0; i<na; i++) if (find_item(nb,b,a[i])!=-1 && find_item(k,c,a[i])==-1) c[k++]=a[i]; for (j=0; j<nb; j++) if (find_item(na,a,b[j])!=-1 && find_item(k,c,b[j])==-1) c[k++]=b[j]; return c; } int *diff_array (int na, int *a, int nb, int *b, int *nc) { //Разность массивов a и b с размерностями na и nb //в новый динамический массив (в массив войдут уникальные элементы, //присутствующие в массиве a, но отсутствующие в b) int *c,i,j; if (na<1) return NULL; delete_equal(&na,a); if (nb<1) return copy_array (na,a,c); delete_equal(&nb,b); //Вычисляем количество элементов в массиве a, отсутствующих в b *nc=0; for (i=0; i<na; i++) { int kc=0; if (find_item(nb,b,a[i])!=-1) kc++; if (kc==0) (*nc)++; } c=(int *)calloc (*nc,sizeof(int)); if (c==NULL) return NULL; //Формируем массив c int k=0; for (i=0; i<na; i++) if (find_item(nb,b,a[i])==-1) c[k++]=a[i]; return c; } void print_array (int n,int *a) { //Выводит массив на экран printf ("\n"); for (int i=0; i<n; i++) printf ("%5d ",a[i]); } void wait() { //Ждет нажатия клавиши printf ("\nPress a key to continue..."); fflush (stdin); getchar(); } const int na=6, nb=5; //Размерности массивов a,b int a[na] = { 4, 4, 2, 5, 3, -1 }, b[nb] = { 2, 3, 4, 4, 1}; //Описали множества как массивы void main () { int nc; printf ("\na="); print_array (na,a); printf ("\nb="); print_array (nb,b); printf ("\nUnion (a,b)="); int *c=union_array (na,a,nb,b,&nc); print_array (nc,c); int nd; printf ("\nCross (a,b)="); int *d=cross_array (na,a,nb,b,&nd); print_array (nd,d); int ne; printf ("\nDifference (a,b)="); int *e=diff_array (na,a,nb,b,&ne); print_array (ne,e); wait(); }
То же самое через множества на Паскале |
На Паскале всё гораздо проще и человечней - тип множества (set
) включён в язык.
Правда, входить в множество могут только величины типа byte
со значениями от 0 до 255 включительно, так что нашу -1 в множестве A заменим на 11.
Зато Паскаль автоматически исключает из множеств одинаковые элементы, поэтому
соответствующую обработку писать не нужно.
Таким образом, вся предыдущая программа может быть сведена к следующему:
type range = set of byte; var a,b : range; procedure writeset (name:string;a:range); var i:byte; begin write (name,' '); for i:=0 to 255 do if i in a then write (ord(i),' '); writeln; end; begin a := [4,4,2,5,3,11]; b := [2,3,4,4,1]; writeset ('a',a); writeset ('b',b); writeset ('a+b',a+b); writeset ('a*b',a*b); writeset ('a\b',a-b); writeln ('Press Enter...'); readln; end.
гостевая; E-mail |