El primer capítulo de la lista enlazada.

Insertar descripción de la imagen aquí

Bienvenido a mi: mundo

Columna de colección: lista vinculada

Espero que el artículo del autor le resulte útil. Corríjame si hay alguna deficiencia. ¡Aprendamos y comuniquémonos juntos!


Prefacio

  • Lo que estoy escribiendo aquí es una pregunta sobre caer en una trampa sobre listas enlazadas. Escribí en detalle todo el proceso de cómo caí en una trampa. Creo que todos también han caído en una trampa. Continuaré actualizando esta columna. . Gracias por tu apoyo.
    ———————— Hacer todo lo posible por el proceso y ser indiferente a los resultados.

Pregunta 1: elimine el enésimo nodo del final de la lista vinculada


Dirección: domicilio del título del DO


Insertar descripción de la imagen aquí

Ideas para resolver problemas:

  • 1. Recorrido violento:
    primero recorremos una vez para encontrar cuántos nodos hay en la lista vinculada (primer recorrido), luego recorremos una segunda vez para encontrar el enésimo nodo del último, lo eliminamos y luego regresamos a la dirección original. Se puede decir que este método es un método de implementación relativamente simple para esta pregunta. Aquí quiero hablar de otro método:

  • 2. Método de tres punteros:
    primero cree tres punteros, puntero de cola, puntero sur y puntero dst. Los punteros sur y dst inicialmente apuntan a la dirección inicial de la lista vinculada, y el puntero de cola apunta a la dirección del byte anterior. el puntero sur. Esto necesita volver a abrir un espacio en el que se puede encontrar la dirección de sur en el siguiente
    diagrama físico al principio :Insertar descripción de la imagen aquí
    Nota: Debido a que las direcciones de la lista vinculada no están conectadas, las direcciones pueden considerarse aleatorias. Las direcciones en la imagen las compilé al azar, solo por conveniencia y fácil observación.

  • Idea: primero deje que el puntero dst se mueva hacia atrás n nodos, de modo que el puntero dst y el puntero sur estén separados por n nodos, y luego deje que estos tres punteros retrocedan un nodo a la vez hasta que el puntero dst apunte al puntero nulo, por lo que Si es así, sur se refiere al enésimo nodo desde abajo ( el concepto de este paso es muy importante y debe pensarse claramente) . En este momento, está la dirección del nodo que se eliminará y también está la dirección de el nodo encima del nodo señalado por el puntero de cola, luego La eliminación se puede completar muy bien.
    Lo anterior es la idea, implementémosla a continuación ;

Diagrama físico al final:
Insertar descripción de la imagen aquí

struct ListNode* removeNthFromEnd(struct ListNode* head, int n ) {
    
    
    // write code here

    //sur指针是指向要删除的那个节点,dst是与sur保持间距n的,tail是sur前一个节点
    struct ListNode* sur = head, *dst = head;
    struct ListNode*tail =(struct ListNode*)malloc(sizeof(struct ListNode));
    tail->next=sur;
    //先让dst指针走n个节点
    while (n--) {
    
    
        dst = dst->next;
    }
    while (dst) {
    
    
        //三个指针一起出发,tail指针始终指向sur指针前前一个节点 
        dst = dst->next;
        sur = sur->next;
        tail = tail->next;

    }
    //删除
    if (head == sur) {
    
    
        //如果sur没动说明要删的就在第一个
        head = head->next;
        sur = head->next;
    } else {
    
    
        //要删的只要找到sur指针的前一个节点,就可以让sur后一个节点与之相连
        tail->next = sur->next;
    }
    return head;
}

Pregunta 2: El nodo intermedio de la lista vinculada


Dirección: dirección del DO


Insertar descripción de la imagen aquí
Ideas para resolver problemas:

  • 1. Método de recorrido violento:
    de acuerdo con el pensamiento normal de esta pregunta, primero debe atravesar el número de todos los nodos en la lista vinculada, luego puede obtener el punto medio y finalmente devolver la dirección que apunta a ese punto; este método es Muy común, no entraré en detalles aquí, quiero hablar en detalle sobre el siguiente método:
  • 2.Método de puntero rápido y lento:
    La idea de este método es: primero establecer dos punteros: lento y rápido, que son punteros rápidos y lentos respectivamente. Primero, ambos punteros apuntan a la posición inicial de la lista vinculada, el lento se mueve al siguiente nodo y el rápido se mueve a los siguientes dos nodos. , hasta que el puntero rápido se detenga, ¿cuándo se detendrá el puntero rápido? Debe haber diferentes situaciones. Si el nodo de la lista vinculada es un número par, entonces rápido irá hasta que esté vacío, y si el punto de resumen de la lista vinculada es un número impar, luego rápido se detendrá en el punto final.
    ----Si es un número impar: diagrama lógico:
    primer paso: Insertar descripción de la imagen aquí
    segundo paso:
    Insertar descripción de la imagen aquí
    tercer paso
    Insertar descripción de la imagen aquí

Si es un número par:
diagrama lógico:
primer paso: Insertar descripción de la imagen aquí
segundo paso:
Insertar descripción de la imagen aquí
tercer paso:
Insertar descripción de la imagen aquí
cuarto paso:
Insertar descripción de la imagen aquí

Código:

struct ListNode* middleNode(struct ListNode* head ) {
    
    
    // write code here
	//设置快慢指针
    struct ListNode*sur=head,*dst=head;
	//当dst指针为空或dst指向的next为空就停下
    while(dst && dst->next)
    {
    
    
        sur=sur->next;
        dst=dst->next->next;
    }
	
    return sur;
}

Pregunta 3: fusionar dos listas enlazadas ordenadas


Dirección: dirección del DO


Insertar descripción de la imagen aquí
Ideas para resolver problemas:

En primer lugar, las listas enlazadas son diferentes de las listas secuenciales y algunas ideas no funcionarán, pero también tienen sus ventajas. Las listas enlazadas están conectadas un nodo a la vez y se pueden desmantelar en cualquier momento; utilizando el método de fusión, podemos Primero cree dos punteros y
deje que los dos conjuntos de listas vinculadas que deben fusionarse se comparen desde sus posiciones iniciales. Se inserta un puntero al final del valor más pequeño y el otro puntero es para encontrar el nodo anterior que debe fusionarse. insertado, para facilitar la inserción de la cola;
Insertar descripción de la imagen aquí
Compare 1 <2, inserte 1 en la cola. Si es la primera inserción, el puntero de la cabeza y el puntero de la cola deben apuntar a la dirección de 1 al mismo tiempo; si no es la primera inserción, entonces la dirección de Head1 se debe dar a tail->next, y luego dejar que el puntero de cola apunte a tail->next, y finalmente dejar que pHead1 apunte al siguiente nodo;
Insertar descripción de la imagen aquí

  • Luego 2 <3, inserte la dirección de 2 al final, igual que en los pasos anteriores;
    Nota: Esta no es la primera inserción después de este punto. Recuerde dejar que el puntero de cola apunte al siguiente nodo de cola;

    Insertar descripción de la imagen aquí
    Los siguientes pasos son casi los mismos:
    hasta que desaparezca una lista vinculada, inserte directamente la cola de la lista vinculada restante; finalmente, devuelva el
    Insertar descripción de la imagen aquí
    Insertar descripción de la imagen aquí
    puntero principal;
    ¿Pero es esto correcto?
    No, hay otro paso que olvidamos. Si una de las dos listas vinculadas está vacía, el resultado de este programa definitivamente informará un error, por lo que tenemos que hacer un juicio al principio. Si una de las dos listas vinculadas está vacía , luego regresa directamente a la otra lista vinculada. ;

Código:

struct ListNode* Merge(struct ListNode* pHead1, struct ListNode* pHead2 ) {
    
    
    // write code here
    //如果其中一个链表为空,则直接返回另一个链表
    if(pHead1==NULL)
        return pHead2;
    if(pHead2==NULL)
        return pHead1;
         
    struct ListNode* head = NULL, *tail = NULL;
    //判断哪个链表先为空,就跳出去
    while (pHead1 && pHead2) {
    
    
        if (pHead1->val < pHead2->val) {
    
    
            if (tail == NULL) {
    
    
                //第一次尾插
                head = tail = pHead1;
                
            } else {
    
    
                //不是第一次尾插
                tail->next = pHead1;
                tail=tail->next;
                
            }
            //让篇pHead1指针找到下一个结点
            pHead1 = pHead1->next;
            
        } else {
    
    
            if (tail == NULL) {
    
    
                //第一次尾插
                head = tail = pHead2;
            } else {
    
    
                //不是第一次尾插
                tail->next = pHead2;
                tail=tail->next;
            }
            //让篇pHead2指针找到下一个结点
            pHead2 = pHead2->next;
        }
    }
    //判断哪个链表先为空,然后让另一个链表直接尾插入;
if(pHead1)
    tail->next=pHead1;

if(pHead2)
    tail->next=pHead2;

    return head;
}

Resumir

Aquí, me gustaría agradecer a los veteranos por mirar, y aquí, los niños quisieran agradecer a todos por su apoyo. Las preguntas anteriores se basan en las habilidades actuales de los niños. Si hay mejores métodos, pueden discutirlos juntos en el Área de comentarios. En el futuro, a medida que aumente la reserva de conocimientos del niño, ¡el niño definitivamente la optimizará! !


Al final del día:
todavía quiero decirte:
---------- Haz todo lo posible por el proceso y sé indiferente a los resultados, esto
también es lo que me digo a mí mismo.

Supongo que te gusta

Origin blog.csdn.net/m0_66780695/article/details/132279076
Recomendado
Clasificación