¿Comparar dos conjuntos de igualdad de forma recursiva?

Soy bastante nuevo en la programación en general y estoy tratando de construir una función que tome como entrada dos conjuntos, que pueden contener otros conjuntos (a (bc) de (fg (h)), (abc (def)) por ejemplo, y devuelve si son iguales o no. Estoy trabajando con un esquema si eso ayuda, pero realmente estoy tratando de visualizar cómo podría hacerlo. Gracias por la ayuda de antemano

preguntado el 16 de mayo de 11 a las 19:05

3 Respuestas

Un enfoque recursivo simple es elegir un elemento del conjunto A y buscar un elemento igual en el conjunto B. Si se encuentra uno, elimine los dos elementos de A y B y recurra. Deténgase con éxito si ambos conjuntos están vacíos; detenerse con falla si exactamente uno está vacío o si el elemento seleccionado de A no tiene un elemento correspondiente en B.

contestado el 17 de mayo de 11 a las 00:05

Eso suena muy, muy O (n²). Hay formas O (n) amortizadas de resolver el problema del OP. - Chris Jester-Young

Si esto es O (n * n) depende de cómo se implementen "elegir un elemento" y "buscar un elemento igual". Si los conjuntos se pueden ordenar, luego de ordenar, "buscar un elemento igual" (o fallar) se puede implementar en O (1) si "elegir un elemento" se implementa como "elegir el primer elemento". Pero eso es O (n lg n) para la clasificación. No se de ninguno recursiva manera de hacerlo mejor. - Ted Hopp

Algunos idiomas tienen tipos de conjuntos integrados, incluido Racket. Entonces, el único problema es convertir una lista (que puede contener otras listas) en conjuntos anidados. Entonces algo como esto: (advertencia - código completamente no probado)

(require racket/set)
(define (recursive-make-set obj)
  (cond
    [(list? obj) (list->set (map recursive-make-set obj))]
    [else obj]))

Básicamente, dejamos los átomos solos y construimos un conjunto a partir de una lista usando la función incorporada list->set funcionar en convertido recursivamente elementos.

contestado el 17 de mayo de 11 a las 00:05

Dos puntos clave: (a) prueba para determinar la similitud del tipo de coincidencia de los componentes individuales (b) prueba para detectar valores coincidentes cuando se llega a los valores del elemento "principal"

Sea cual sea el lenguaje de programación que use, si miramos una parte de las listas, por ejemplo, (a (bc) ...) y (abc ...), notaremos después de ver "a" que cada uno es de un diferente tipo. La primera lista sigue a "a" con una lista, mientras que la segunda lista sigue a a con otro elemento que no es de la lista. Los idiomas probablemente fallarán (señalarán un error de algún tipo) o le permitirán considerar cada uno de estos tipos diferentes de manera similar, pero generalmente brindan una forma de consultar el tipo.

En el esquema (y no recuerdo exactamente), la primera lista tiene su valor de automóvil como a y su valor de cdr es la lista ((bc) ...). La segunda lista tiene un valor de coche de a, pero el cdr devuelve la lista (bc ...). Estos dos no pueden ser iguales a menos que el lenguaje ofrezca una visión diferente de la "igualdad".

Este tipo de prueba para el tipo de objeto sería el primer paso para ver si las listas son iguales.

A continuación, probamos los valores de los elementos básicos en las ubicaciones correspondientes dentro de las estructuras idénticas ya verificadas. Debemos atravesar las estructuras de la manera adecuada (es decir, dependiendo de los detalles de la estructura).

Los detalles del algoritmo de desplazamiento dependen del lenguaje de programación. Algunos idiomas brindan más ayuda que otros para evitar errores y probar la uniformidad.

Podemos utilizar enfoques recursivos o iterativos. Con esquema, y ​​conceptualmente, lo recursivo es lo más natural.

Ejemplo de pseudocódigo donde tanto el tipo como el valor son manejados por la prueba compuesta =?

function f (l1, l2):
(=? car(l1) car(l2))
and
(f cdr(l1) cdr(l2))

Notamos la recursividad. Lo que hace es que, si obtiene un elemento simple, prueba la igualdad y devuelve ese valor. Si esa función se llamó directamente, entonces esa es la respuesta final, si se llamó de forma recursiva, entonces envía esa respuesta de regreso a la cadena de llamadas de función haciendo que algunos anidados (f cdr (l1) cdr (l2)) devuelvan falso o verdadero y en última instancia, hacer la llamada de nivel más alto también devuelve falso o potencialmente aún puede devolver verdadero (tenga en cuenta el requisito "y" y cómo funciona ... verdadero viene solo si todas las partes son verdaderas, mientras que las falsas ocurren si alguna parte es falsa). De manera similar, si la función obtiene una lista, entonces prueba la parte del automóvil y "y" este valor t / f con lo que sea que obtenga cuando se llame a sí misma nuevamente de forma recursiva en el resto de la lista. Por lo tanto, esta función maneja tanto listas como no listas en cualquier estructura intrincada de sublistas que la alimente. [recuerde, asumimos que =? manejó tanto las verificaciones de tipo como de valor, por ejemplo, de modo que (=? b '(b)) sería #f]

[Ver también http://cs.gettysburg.edu/~tneller/cs341/scheme-intro/exercises.html#Equivalence por lo que podría usar para probar la equivalencia.]

contestado el 17 de mayo de 11 a las 01:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.