Juicio de la lista vinculada

El problema

Hoy pregunté: sabemos que en una lista vinculada, si el siguiente atributo de un nodo apunta a otro nodo de la lista vinculada, entonces la lista vinculada tiene un anillo. Entonces, la pregunta de hoy es: cómo juzgar si una lista vinculada individualmente tiene forma de anillo. Qué peligros ocultos traerá una lista vinculada al programa.

Consejo: Puede pensar en seleccionar un nodo en la lista vinculada y luego hacer un ciclo de la lista vinculada. Si el ciclo llega a este nodo, indica que la lista vinculada tiene un anillo, pero el problema con este método es cómo asegurarse de que el nodo seleccionado esté en la lista vinculada. Esto es en realidad equivalente a juzgar si la lista vinculada tiene un timbre y si el problema ha regresado.

Respuesta

En realidad, hay una solución fija para este problema, que es la forma de utilizar punteros rápidos y lentos. Usando dos referencias al encabezado de la lista vinculada, y luego iterando a través del bucle, un puntero se mueve a un bit a la vez y un puntero se mueve dos bits a la vez, entonces solo habrá dos casos:

  1. La lista vinculada no tiene anillos, y el puntero rápido se mueve al siguiente lugar vacío;
  2. La lista vinculada tiene un anillo, e incluso los punteros deben encontrarse;

El primer caso es indudablemente, para el segundo caso, el puntero lento siempre se moverá al anillo de la lista vinculada, y luego el puntero rápido siempre se pondrá al día con el puntero lento, y el puntero rápido tomará dos pasos a la vez, y no "sobrepasará" el lento Los punteros se encontrarán eventualmente.

public class Test {
    public static void main(String[] args) {

        IntegerNode list = new IntegerNode(0);
        IntegerNode prep = list;
        IntegerNode ringStart = null;
        for (int i = 1; i < 100; i++) {
            IntegerNode node = new IntegerNode(i);
            prep.next = node;
            prep = node;
            if (i == 93) {
                ringStart = node;
            }
            if (i == 99) {
                node.next = ringStart;
            }
        }
        System.out.println(hasRing(list));


    }

    private static boolean hasRing(IntegerNode list) {
        boolean result = false;
        IntegerNode one = list;
        IntegerNode two = list;
        IntegerNode meetingPoint = null;

        while (two != null) {
            one = (IntegerNode) one.next;
            two = (IntegerNode) two.next;
            if (two != null) {
                two = (IntegerNode) two.next;
            }
            if (one == two) {
                result = true;
                meetingPoint = one;
                System.out.println("交汇点:" + one.getValue());
                break;
            }
        }
        return result;
    }
}

Lo anterior es el código para juzgar si la lista vinculada tiene un anillo.

Luego, después de saber que la lista vinculada tiene anillos, todavía quedan los siguientes cálculos:

  1. Qué nodo es la posición inicial del anillo (es decir, iterando hacia atrás desde el encabezado de la lista vinculada, el primer nodo encontrado en el anillo);
  2. La longitud del anillo;

Para los dos problemas anteriores, primero registramos los siguientes valores:

  1. La longitud de la lista vinculada (es decir, el número de Nodo) es longitud;
  2. El número de nodos que no están en el anillo es a;
  3. El número de nodos en el anillo es b;
  4. El punto de encuentro es el h-ésimo nodo en el ring;

Luego está la siguiente ecuación:

2 (a + h-1) = a + n * b + h-1

Donde n es el número de vueltas del anillo que caminó el puntero rápido durante el primer encuentro.

Se puede concluir que:

a + h-1 = n * b

Es decir, cuando el primer encuentro, el número de pasos del puntero lento es un múltiplo entero de la longitud del anillo.

Si, después de que se encuentran, un puntero comienza desde el punto de encuentro y uno comienza desde el encabezado de la lista vinculada, un paso a la vez, entonces al caminar desde el encabezado de la lista vinculada a la posición inicial del anillo, toma el paso a-1 y otro Un puntero también camina a-1 paso, que es n b-h paso, y el segundo desde la posición h-ésima del anillo para caminar n b-h resulta ser la posición inicial del anillo, por lo que la posición de revelación y el método para juzgar el anillo son los siguientes:

//计算环的第一个点
if (result) {
    one = meetingPoint;
    two = list;
    while (one != two) {
        one = (IntegerNode) one.next;
        two = (IntegerNode) two.next;
    }
    System.out.println("环的第一个点:" + one.getValue());
    int count = 1;
    two = (IntegerNode) two.next;
    while (one != two) {
        two = (IntegerNode) two.next;
        count++;
    }
    System.out.println("环的长度是" + count);

}

En cuanto a los peligros ocultos de la lista vinculada al programa, es muy simple: si no juzgamos esto cuando recorremos la lista, se producirá un bucle infinito.

Publicado 19 artículos originales · elogiado 8 · visitas 4040

Supongo que te gusta

Origin blog.csdn.net/u014068277/article/details/103951222
Recomendado
Clasificación