Una lista enlazada consiste en una serie de nodos o elementos donde, además de almacenarse el dato en sí, tiene información que le indica cuál es el nodo siguiente y/o anterior.
En C esto se consigue mediante las estructuras. Una estructura (struct) agrupa un conjunto de variables o campos, y permite trabajar con ella como si se tratara de un tipo de dato más. Y la forma de indicarle a cada nodo cuál es su nodo siguiente es usando variables de tipo puntero en la estructura.
Un poco de código para que lo entiendas:
typedef struct _nodo {
int valor;
_nodo* anterior;
_nodo* siguiente;
} nodo;
Las variables anterior y siguiente son punteros a nodo, es decir, enlazan el nodo actual a otros nodos. Así para enlazar dos nodos, únicamente debes poner algo como:
nodo1.siguiente = &nodo2;
nodo1.anterior = &nodo0;
En una lista enlazada lo normal es que haya un nodo que sea el primero y otro que sea el último. Estos casos son especiales. El primer nodo, su puntero anterior apuntará a NULL, es decir, no existe un nodo anterior. El último nodo es similar, pero con el puntero a siguiente.
Por último, para recorrer una lista enlazada, basta con crear una variable auxiliar que sea puntero a nodo:
nodo* aux;
Luego, con un bucle se puede recorrer toda la lista de la siguiente manera (es solo un ejemplo):
aux = &primer_nodo;
while (aux != NULL) {
aux = aux->siguiente;
// ... y lo que sea
}
Básicamente, la idea es jugar con esto. No he querido entrar en más detalle porque creo que esto te será suficiente. No obstante, si necesitas ayuda sobre punteros, o sintaxis de C, no dudes en preguntar.