Como inserir um elemento em qualquer posição — e por que os elementos precisam ser deslocados
Inserir no final de uma lista sequencial é simples: coloca na próxima posição livre e incrementa o contador. Mas e se precisarmos inserir no meio?
Imagine a lista [9, 3, 4, 1] e queremos inserir o elemento 12 na posição 2 (entre o 3 e o 4). O resultado esperado é [9, 3, 12, 4, 1].
O algoritmo tem 3 etapas:
i é válido (entre 0 e nroElem)?
i, mover cada elemento uma posição para frente.
A[i] e incrementar nroElem.
Visualizando para inserir 12 na posição i=2 na lista [9, 3, 4, 1]:
| Passo | Índice 0 | Índice 1 | Índice 2 | Índice 3 | Índice 4 |
|---|---|---|---|---|---|
| Lista inicial | 9 | 3 | 4 | 1 | — |
| j=4: A[4] ← A[3] | 9 | 3 | 4 | 1 | 1 |
| j=3: A[3] ← A[2] | 9 | 3 | 4 | 4 | 1 |
| j=2: condição j>i falsa — para | 9 | 3 | 4 | 4 | 1 |
| A[2] = 12, nroElem++ | 9 | 3 | 12 | 4 | 1 |
inserirElemLista
bool inserirElemLista(LISTA* l, REGISTRO reg, int i) {
int j;
// Verifica: lista cheia OU índice fora do intervalo válido [0, nroElem]
if ((l->nroElem >= MAX) || (i < 0) || (i > l->nroElem))
return false;
// Desloca elementos da posição nroElem até i+1 uma casa para a direita
for (j = l->nroElem; j > i; j--)
l->A[j] = l->A[j - 1];
// Insere o novo registro na posição i
l->A[i] = reg;
l->nroElem++;
return true;
} /* inserirElemLista */
for começa em j = nroElem? O último elemento válido está em nroElem - 1, então ele precisa ir para nroElem. Começar em nroElem e fazer A[j] = A[j-1] realiza exatamente esse movimento.
i até nroElem), sobrescreveríamos cada elemento antes de movê-lo. O deslocamento deve começar pelo final para preservar todos os valores.
Em Java, o ArrayList faz exatamente o mesmo deslocamento internamente — mas esconde toda essa complexidade:
ArrayList<Integer> lista =
new ArrayList<>();
lista.add(9);
lista.add(3);
lista.add(4);
lista.add(1);
// Inserir 12 na posição 2:
lista.add(2, 12);
// Java faz o deslocamento
// internamente — você não vê
System.out.println(lista);
// [9, 3, 12, 4, 1]
LISTA lista; inicializarLista(&lista); REGISTRO reg; reg.chave=9; inserirElemLista(&lista,reg,0); reg.chave=3; inserirElemLista(&lista,reg,1); reg.chave=4; inserirElemLista(&lista,reg,2); reg.chave=1; inserirElemLista(&lista,reg,3); // Inserir 12 na posição 2: reg.chave = 12; inserirElemLista(&lista, reg, 2); exibirLista(&lista); // Lista: " 9 3 12 4 1 "
inserirElemLista retorna false.
No pior caso (inserir na posição 0), precisamos deslocar todos os nroElem elementos. Isso torna a inserção uma operação O(n) — linear em relação ao tamanho da lista.
| Onde inserir | Deslocamentos | Caso |
|---|---|---|
Posição final (i = nroElem) | 0 | Melhor caso — O(1) |
| Posição do meio | nroElem/2 | Caso médio — O(n/2) |
Posição inicial (i = 0) | nroElem | Pior caso — O(n) |
ArrayList.add(index, value) tem o mesmo custo O(n) para inserções no meio ou no início. Se você precisa de inserções frequentes no início ou no meio, o LinkedList do Java (ou a lista ligada em C) é mais eficiente — mas perde no acesso aleatório.