Empilhar três lista em c

Boa tarde eu criei três lista: l,l2 e l3 e preciso empilhar e desempilhar mas não sei como fazer. Alguém pode me ajudar?
segue o codigo das tres listas:

#include <stdio.h>
#include <stdlib.h>

struct lista
{
char nome;
struct lista* prox;
};
typedef struct lista Lista;

Lista* inicializa (void)
{
return NULL;
}

Lista *insere (Lista* l, char nom1)
{
Lista *novo = (Lista*) malloc(sizeof(Lista));
novo->nome = nom1;
novo->prox = l;
}

void imprime (Lista *l,Lista *l2, Lista *l3) {
Lista* p;
Lista* p2;
Lista* p3;
printf("primeiro nome: ");
for (p = l; p != NULL; p = p->prox)
{
 printf("%c", p->nome);
}
printf("\n");
printf("segundo nome: ");
for (p2 = l2; p2 != NULL; p2 = p2->prox)
{
 printf("%c", p2->nome);
}
printf("\n");
printf("terceiro nome: ");
for (p3 = l3; p3 != NULL; p3 = p3->prox)
{
 printf("%c", p3->nome);
}
printf("\n");
}

int main (void)
{
Lista *l;
Lista *l2;
Lista *l3;
l = inicializa();
l2 = inicializa();
l3 = inicializa();
l = insere(l, 'a');
l = insere(l, 'z');
l = insere(l, 'i');
l = insere(l, 'n');
l = insere(l, 'o');
l = insere(l, 't');
l = insere(l, 'n');
l = insere(l, 'a');
l2 = insere(l2, 'a');
l2 = insere(l2, 's');
l2 = insere(l2, 'u');
l2 = insere(l2, 'o');
l2 = insere(l2, 's');
l3 = insere(l3, 's');
l3 = insere(l3, 'i');
l3 = insere(l3, 'a');
l3 = insere(l3, 'r');
l3 = insere(l3, 'o');
l3 = insere(l3, 'm');
imprime(l,l2,l3);
return 0;
 }

Vamos la

vc esta falando em Lista. e em empilhar (inserir no fim) e desempilhar ( pegar do fim ).

O que é isso? é uma Pilha. Uma Pilha que pode utilizar, internamente, uma lista encadeada.

imagine este codigo

Pilha *p = criar_pilha();
char x,y,z;
int tamanho;
empilhar(p, 'a');
empilhar(p, 'b');
empilhar(p, 'c');
tamanho = tamanho(p); // 3 numeros
x=desempilhar(p); // return c
y=desempilhar(p); // return b
z=desempilhar(p); // return a
tamanho = tamanho(p); // 0 numeros - ta vazio

essa interface ta bonita né?

o que é o cria_pilha? vc inicializa uma estrutura assim

struct no { char letra, no proximo; };
typedef struct no No;

struct pilha { No * primeiro, int tamanho; }
typedef struct pilha Pilha;

uma sequencia de nos é uma lista. vc pode chamar isso de lista se quiser.

vc vai criar uma pilha ( via malloc ) cujo primeiro vai ser NULL e tamanho 0

ao empilhar vc vai

  1. navegar com while ate achar um no cujo proximo é NULL, e ai vc cria um No com o char que vc quer. e ai incrementa o valor do tamanho. não altera o ponteiro primeiro, senào a magica acaba.

ao desempilhar vc
2. navegar com while ate achar um no cujo proximo->proximo é NULL, ai vc retorna proximo->proximo->letra, tomando o cuidado pra fazer proximo = NULL;

mais ou menos assim

char desempilhar( Pilha *p ) {
  char c;
  No *antepenultimo, *ultimo;
  if ( p->primeiro == NULL ) { 
     /* nada pra imprimir, e agora? */
  } else if (p->primeiro->proximo == NULL ) { 
     /* so tem um, retorna isso */
     c = p->primeiro->letra;
     p->primeiro = NULL;
     return c;
  } else {
     antepenultimo = p->primeiro; // o primeiro
     ultimo = p->primeiro->proximo; // o segundo
     while ( ultimo->proximo != NULL ) {
        antepenultimo = ultimo; 
        ultimo = ultimo->proximo;
     }
     // chegou aqui? a gente sabe que ultimo é o ultimo elemento nao nulo
     // e antepenultimo é um antes dele. e?
     c = ultimo->letra;
     antepenultimo->proximo = NULL;
     return c;
  }
} 

pode simplificar? pode. e muito. vc pode

  1. uma vez que é uma pilha, fazer uma lista q ao inves de guardar o proximo, guarda o anterior ( que meio q é a sua logica ). assim a sua Pilha guarda o ultimo. empilhar e desempilhar fica muito mais facil.

  2. sua pilha por armazenar o primeiro e ultimo no. ai simplifica um pouco

  3. vc pode usar uma lista duplamente encadeada