pi tp 10
Tópicos: Conversões entre Arrays e Listas Ligadas, Inversão in-place, e Inserção Ordenada.
1. Converter Lista Ligada para Array (list2array)
Copia os valores de uma lista ligada para um array pré-alocado, até ao limite N ou até a lista terminar. Retorna o número de elementos efetivamente copiados.
int list2array(LInt l, int v[], int N){
int i = 0;
while(i < N && l != NULL){
v[i] = l->valor;
l = l->prox;
i ++;
}
return i;
}2. Converter Array para Lista Ligada (array2List)
Cria uma lista ligada a partir de um array. O truque aqui é percorrer o array de trás para a frente (do índice N-1 até 0). Como estamos sempre a inserir os nós à cabeça da lista (comportamento de stack), lê-los ao contrário garante que a lista final fica com a mesma ordem do array original.
LInt array2List(int v[], int N){
LInt a = NUll, nova;
for(int i = N - 1; i >= 0; i --){
nova = malloc(sizeof(struct lligada));
nova->valor = v[i];
nova->prox = a; // o novo nó aponta para o resto da lista construida
a = nova; // O inicio da lista passa a ser o novo nó
} return a;
}3. Inverter uma Lista Ligada (reverseL)
Inverte a ordem dos nós sem criar uma nova lista (sem usar malloc), apenas redirecionando os apontadores prox. É a abordagem mais eficiente .
LInt reverseL (LInt l){
LInt x, r = NULL; // 'r' será a nova cabeça (e também o anterior na iteração)
while (l != NULL){
x = l; // guardamos o nó atual
l = l->prox; // Avançamos na lista original
x->prox = r; // Damos a volta à seta do nó atual
r = x; // O atual passa a ser o anterior para a próxima volta
}
return r; // Retornamos a cabeça da lista invertida
}4. Inserção numa Lista Ordenada (InsereOrd)
Insere um elemento x na posição correta para manter a ordenação da lista, usando a abordagem clássica de dois apontadores (ant e p). Note-se o uso do duplo apontador LInt *l para permitir a modificação da cabeça da lista caso o novo elemento seja o menor de todos.
void InsereOrd(LInt *l, int x){
// 1. Criar um novo nó
LInt n = malloc(sizeof(struct lligada)), p = l;
n->valor = x;
LInt ant = NULL;
LInt p = *l; // ponto de partida para procurar
// 2. procurar o buraco correto
while(p != NULL && p->valor < x){
ant = p;
p = p->prox;
}
//3. Conectar o novo nó ao que ficou à sua direita
n->prox = p;
//4. Conectar o nó à sua esquerda (ou atualizar a cabeça)
if(ant != NULL) ant->prox = n;
else *l = n;
}Main
#include <stdio.h>
#include <stdlib.h>
// 1. A NOSSA ESTRUTURA
typedef struct lligada {
int valor;
struct lligada *prox;
} *LInt;
// 2. AS NOSSAS FUNÇÕES (Exatamente como nas tuas notas)
int list2array(LInt l, int v[], int N) {
int i = 0;
while (i < N && l != NULL) {
v[i] = l->valor;
l = l->prox;
i++;
}
return i;
}
LInt array2List(int v[], int N) {
LInt a = NULL, nova;
for (int i = N - 1; i >= 0; i--) {
nova = malloc(sizeof(struct lligada));
nova->valor = v[i];
nova->prox = a;
a = nova;
}
return a;
}
LInt reverseL(LInt l) {
LInt x;
LInt r = NULL;
while (l != NULL) {
x = l;
l = l->prox;
x->prox = r;
r = x;
}
return r;
}
void InsereOrd(LInt *l, int x) {
LInt n = malloc(sizeof(struct lligada));
n->valor = x;
LInt ant = NULL;
LInt p = *l;
while (p != NULL && p->valor < x) {
ant = p;
p = p->prox;
}
n->prox = p;
if (ant != NULL) {
ant->prox = n;
} else {
*l = n;
}
}
// 3. O MAIN PARA O PYTHON TUTOR
int main() {
// Passo 1: Começamos com um array simples
int arrayOrigem[3] = {10, 20, 30};
// Passo 2: Transformamos o array numa Lista Ligada
// Vais ver as 3 caixas a serem criadas no "Heap"
LInt minhaLista = array2List(arrayOrigem, 3);
// Passo 3: Inserimos elementos mantendo a ordem
// O 25 vai entrar no meio (entre o 20 e o 30)
InsereOrd(&minhaLista, 25);
// O 5 vai entrar no início (muda o apontador principal)
InsereOrd(&minhaLista, 5);
// Passo 4: Damos a volta à lista!
// Fica de olho nas setas (prox), vais vê-las a inverter a direção
minhaLista = reverseL(minhaLista);
// Passo 5: Guardamos a lista final num novo array vazio
int arrayDestino[10];
int elementosCopiados = list2array(minhaLista, arrayDestino, 10);
return 0;
}