typedef struct no {
int v;
struct no* prox;
} No;
void insere_ordenado (No** l, int v) {
if (*l == NULL || (*l)->v > v) {
No* n = (No*) malloc (sizeof(No));
n->v = v;
n->prox == *l;
*l = n;
}
else
if ((*l)->v == v)
printf("Elemento %d já existente.\n", v);
else
insere_ordenado (&(*l)->prox, v);
}
void insere_ordenado (No** l, int v) {
if (*l == NULL || (*l)->v > v) {
No* n = (No*) malloc (sizeof(No));
n->v = v;
n->prox = *l;
*l = n;
return;
}
No* p = *l;
while (1) {
if (p->prox == NULL || p->prox->v > v) {
No *n (No*) malloc (sizeof(No));
n->v = v;
n->prox = p->prox;
p->prox = n;
return;
}
if (p->prox->v == v) {
printf("Elemento %d já existente.\n", v);
return;
}
p = p->prox;
}
}
void insere_ordenado (No** l, int v) {
while (1) {
if (*l == NULL || (*l)->v > v) {
No* n = (No*) malloc (sizeof(No));
n->v = v;
n->prox = *l;
*l = n;
return;
}
if ((*l)->v == v) {
printf("Elemento %d já existente.\n", v);
return;
}
l = &(*l)->prox;
}
}
Por que é necessário utilizar um parâmetro do tipo No**? Se a
lista tivesse um nó cabeça, um parâmetro do tipo No* seria
adequado?
Precisamos utilizar um parâmetro do tipo No** porque o apontador que marca o nó inicial da lista pode ser alterado. No caso de listas com nó cabeça, as inserções não alteram o apontador para o nó cabeça, e, portanto, o parâmetro do tipo No* seria suficiente.
typedef struct no {
int v;
struct no *prox;
} No;
No* remove_zeros(No* l) {
if (l == NULL)
return NULL;
if (l->v == 0) {
No* r = l;
l = l->prox;
free(r);
return remove_zeros(l);
}
else{
l->prox = remove_zeros(l->prox);
return l;
}
}
typedef struct no_arv { typedef struct no_lista {
int v; int v;
struct no_arv *esq, *dir; struct no_lista *prox;
} No_arv; } No_lista;
No_lista* monta_lista(No_arv *arv);
Para que você obtenha nota integral nesta questão, sua solução, além
de correta
/* Percorre a lista referente à sub-árvore esquerda
para fazer a concatenação entre as listas. */
No_lista* monta_lista(No_arv* arv) {
if (arv == NULL)
return NULL;
No_lista* lesq = monta_lista(arv->dir);
No_lista* l = malloc (sizeof(No_lista));
l->v = arv->v;
l->prox = monta_lista(arv->esq);
if (lesq == NULL)
return l;
No_lista* aux = lesq;
while (aux->prox != NULL)
aux = aux->prox;
aux->prox = l;
return lesq;
}
/* Cria listas, indicando um apontador para o início e outro
para o final da lista. Desta forma, é possível fazer a concatenação
de forma eficiente.
*/
void monta_aux(No_arv *arv, No_lista** prim, No_lista** ult) {
No_lista *l = malloc (sizeof(No_lista));
l->v = arv->v;
if (arv->dir) {
No_lista *ult_lesq;
monta_aux(arv->dir, prim, &ult_lesq);
ult_lesq->prox = l;
}
else
*prim = l;
if (arv->esq)
monta_aux(arv->esq, &l->prox, ult);
else
*ult = l;
}
No_lista* monta_lista(No_arv* arv) {
if (arv == NULL)
return NULL;
No_lista *prim, *ult;
monta_aux(arv, &prim, &ult);
ult->prox = NULL;
return prim;
}
/* Esta versão faz um percurso inordem invertido na árvore
e vai montando a lista do último nó até o primeiro.
*/
No_lista* aux_monta_lista(No_arv* arv, No_lista* prox) {
No_lista *l = malloc (sizeof(No_lista));
l->v = arv->v;
if (arv->esq != NULL)
l->prox = aux_monta_lista(arv->esq, prox);
else
l->prox = prox;
if (arv->dir != NULL)
return aux_monta_lista(arv->dir, l);
else
return l;
}
No_lista* monta_lista(No_arv* arv) {
if (arv == NULL)
return NULL;
return aux_monta_lista(arv, NULL);
}
typedef struct no23{
int nch; /* Número de chaves (1 ou 2) no nó */
struct no23 *esq, *cen, *dir; /* Apontadores esquerdo, central e direito */
int chesq, chdir; /* Chaves esquerda e direita */
} No23;
void libera(No23* no) {
if (no != NULL) {
if (no->esq != NULL) { /* Não é folha */
libera(no->esq);
libera(no->cen);
if (no->nch == 2)
libera(no->dir);
}
free(no);
}
}