¿Cuál es la forma más eficiente de verificar si un elemento es parte de un conjunto?

La estructura de datos de conjunto disjunto se desarrolló exactamente para esto. Es muy simple de codificar y entender. Conjuntos disjuntos

Aquí está mi implementación en C ++:

archivo de cabecera:

  #ifndef DISJOINT_SET_H
 #define DISJOINT_SET_H
 #include 
 #include 
 #include 
 usando el espacio de nombres estándar;
 nodo de estructura {
     struct elem * head;
     struct elem * tail;
     int no_elements;
 };

 struct elem {
     struct node * rep;
     struct elem * next;
     clave int;
 };

 clase disjoint_set
 {
 público:
     unordered_map  elements_pair;
     disjoint_set ();
     struct elem * find_elem (clave int);
     struct node * make_set (int key);
     struct node * find_set (struct elem * u);
     struct node * find_set (int key);
     struct node * union_set (struct elem * u, struct elem * v);
     struct node * union_set (int u, int v);
 };

 #endif // DISJOINT_SET_H

archivo de clase:

  #include "disjoint_set.h"
 #include 

 disjoint_set :: disjoint_set ()
 {
 }

 struct elem * disjoint_set :: find_elem (int key) {
     return elements_pair [clave];
 }

 struct node * disjoint_set :: make_set (int key) {
     struct node * rep = new struct node;
     rep-> no_elements = 1;
     struct elem * element = new struct elem;
     elemento-> rep = rep;
     elemento-> siguiente = NULL;
     elemento-> clave = clave;
     rep-> head = elemento;
     rep-> cola = elemento;
     elements_pair [clave] = elemento;
     representante de retorno;
 }

 struct node * disjoint_set :: find_set (struct elem * element) {
     elemento de retorno-> rep;
 }

 struct node * disjoint_set :: find_set (int key) {
     return find_set (elements_pair [clave]);
 }

 struct node * disjoint_set :: union_set (struct elem * u, struct elem * v) {
     struct node * rep, * to_del_rep;
     rep = find_set (u) -> no_elements> find_set (v) -> no_elements?  find_set (u): find_set (v);
     to_del_rep = find_set (u) -> no_elements> find_set (v) -> no_elements?  find_set (v): find_set (u);
     struct elem * tail, * to_del_head;
     cola = rep-> cola;
     to_del_head = to_del_rep-> head;
     hacer{
         cola-> siguiente = to_del_head;
         to_del_head-> rep = rep;
         rep-> no_elements ++;
         cola = cola-> siguiente;
     } while (to_del_head-> next! = NULL);
     rep-> tail = to_del_head;
     eliminar to_del_rep;
     representante de retorno;
 }

 struct node * disjoint_set :: union_set (int u, int v) {
     return union_set (find_elem (u), find_elem (v));
 }

Si desea “crear un conjunto”, la verificación de “membresía de elementos” debe ser eficiente, entonces
La eficiencia es una propiedad / característica del conjunto, y no el elemento.

La forma más sencilla de hacerlo es implementar el “conjunto” como un “árbol binario equilibrado” (o cualquiera de sus variantes)
El elemento Agregar, Eliminar y Verificar estará todo en tiempo “log (n)” en función de n, el tamaño del conjunto

https://en.wikipedia.org/wiki/Ba