¿Cómo escribir funciones C que modifican el puntero principal de una lista enlazada?

Considere la representación simple (sin ningún Node ficticio) de la Lista enlazada. Las funciones que operan en dichas listas vinculadas se pueden dividir en dos categorías:

1) Funciones que no modifican el puntero principal: Ejemplos de tales funciones incluyen, imprimir una lista enlazada, actualizar miembros de datos de Nodes como agregar un valor dado a todos los Nodes, o alguna otra operación que acceda/actualice datos de Nodes 
. fácil decidir el prototipo de funciones de esta categoría. Siempre podemos pasar el puntero principal como argumento y recorrer/actualizar la lista. Por ejemplo, la siguiente función que agrega x a los miembros de datos de todos los Nodes.

C

void addXtoList(struct Node *node, int x)
{
    while(node != NULL)
    {
        node->data = node->data + x;
        node = node->next;
    }
}    

2) Funciones que modifican el puntero de cabeza:

Los ejemplos incluyen insertar un Node al principio (el puntero principal siempre se modifica en esta función), insertar un Node al final (el puntero principal se modifica solo cuando se inserta el primer Node), eliminar un Node determinado (el puntero principal se modifica cuando el Node eliminado es el primer Node). Puede haber diferentes formas de actualizar el puntero de la cabeza en estas funciones. Discutamos estas formas usando el siguiente problema simple:

“Dada una lista enlazada, escribe una función deleteFirst() que elimine el primer Node de una lista enlazada dada. Por ejemplo, si la lista es 1->2->3->4, entonces debe modificarse a 2->3->4”
El algoritmo para resolver el problema es un proceso simple de 3 pasos: (a) Almacene el puntero principal (b) cambiar el puntero principal para que apunte al siguiente Node (c) eliminar el Node principal anterior. 

Las siguientes son diferentes formas de actualizar el puntero principal en deleteFirst() para que la lista se actualice en todas partes.

2.1) Hacer que el puntero de la cabeza sea global: podemos hacer que el puntero de la cabeza sea global para que se pueda acceder y actualizar en nuestra función. A continuación se muestra el código C que utiliza un puntero de cabeza global.

C

// global head pointer 
struct Node *head = NULL;
  
// function to delete first node: uses approach 2.1
// See http://ideone.com/ClfQB for complete program and output
void deleteFirst()
{
    if(head != NULL)
    {
       // store the old value of head pointer    
       struct Node *temp = head;
         
       // Change head pointer to point to next node 
       head = head->next; 
  
       // delete memory allocated for the previous head node
       free(temp);
    }
}

Vea esto para ver un programa en ejecución completo que utiliza la función anterior.

Esta no es una forma recomendada ya que tiene muchos problemas como los siguientes: 
a) head es accesible globalmente, por lo que puede modificarse en cualquier parte de su proyecto y puede generar resultados impredecibles. 
b) Si hay múltiples listas enlazadas, entonces se necesitan múltiples punteros globales con diferentes nombres.

Vea esto para conocer todas las razones por las que debemos evitar las variables globales en nuestros proyectos. 

Complete Interview Preparation - GFG

2.2) Devolver puntero principal: Podemos escribir deletefirst() de tal manera que devuelva el puntero principal modificado. Quien esté usando esta función, tiene que usar el valor devuelto para actualizar el Node principal. 

C

// function to delete first node: uses approach 2.2
// See http://ideone.com/P5oLe for complete program and output
struct Node *deleteFirst(struct Node *head)
{
    if(head != NULL)
    {
       // store the old value of head pointer
       struct Node *temp = head;
  
       // Change head pointer to point to next node
       head = head->next;
  
       // delete memory allocated for the previous head node
       free(temp);
    }
  
    return head;
}

Ver esto para el programa completo y la salida. 

Este enfoque es mucho mejor que el 1 anterior. Solo hay un problema con esto, si el usuario no asigna el valor devuelto al encabezado, entonces las cosas se complican. Los compiladores de C/C++ permiten llamar a una función sin asignar el valor devuelto. 

C

head = deleteFirst(head);  // proper use of deleteFirst()
deleteFirst(head);  // improper use of deleteFirst(), allowed by compiler

2.3) Usar puntero doble: este enfoque sigue la regla C simple: si desea modificar la variable local de una función dentro de otra función, pase un puntero a esa variable . Entonces podemos pasar el puntero al puntero principal para modificar el puntero principal en nuestra función deletefirst(). 

C

// function to delete first node: uses approach 2.3
// See http://ideone.com/9GwTb for complete program and output
void deleteFirst(struct Node **head_ref)
{
    if(*head_ref != NULL)
    {
       // store the old value of pointer to head pointer
       struct Node *temp = *head_ref;
  
       // Change head pointer to point to next node
       *head_ref = (*head_ref)->next;
  
       // delete memory allocated for the previous head node
       free(temp);
    }
}

Ver esto para el programa completo y la salida. 

Este enfoque parece ser el mejor entre los tres, ya que hay menos posibilidades de tener problemas.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *