I saw the @pcccj reply and agree with what it says, about returning the item, and not just write down its value. There are several ways to do this, from a genius algorithm that masterfully manipulates the return of the search function to a simple algorithm that makes use of C’s tools.
Since I’m not that smart, here’s a simple algorithm ;)
#include<stdio.h>
#include<stdlib.h>
// Declara o formato dos nodos da árvore, e cria o tipo
struct nodo {
int Elemento;
struct nodo *Esquerda;
struct nodo *Direita;
};
typedef struct nodo Nodo;
// Insere elementos na árvore
void InsereNodo(Nodo **raiz, Nodo *item) {
if (!*raiz) {
*raiz = item;
return;
}
if (item->Elemento < (*raiz)->Elemento)
InsereNodo(&(*raiz)->Esquerda, item);
else
InsereNodo(&(*raiz)->Direita, item);
}
// Escreve o valor de cada elemento da árvore, in-order
void ListarEmOrdem(Nodo *raiz){
if (raiz->Esquerda)
ListarEmOrdem(raiz->Esquerda);
printf("%d\n", raiz->Elemento);
if (raiz->Direita)
ListarEmOrdem(raiz->Direita);
}
// Percorre a árvore, por profundidade, parando ao encontrar o n-ésimo elemento
void ProcuraProfundidade(Nodo *raiz, int **posicao, int limite, Nodo **NodoEncontrado){
if (raiz->Esquerda)
ProcuraProfundidade(raiz->Esquerda, posicao, limite, NodoEncontrado);
if (!*NodoEncontrado){
if((**posicao)++ == limite){
*NodoEncontrado = raiz;
return;
}
if (raiz->Direita)
ProcuraProfundidade(raiz->Direita, posicao, limite, NodoEncontrado);
}
}
// Função intermediária de busca; mantém uma assinatura decente e lida com exceções
Nodo* Procura(Nodo *raiz, int posicao){
if (posicao < 1)
return NULL;
else if (!raiz)
return raiz;
else {
Nodo *NodoEncontrado = NULL;
int *inicial = malloc(sizeof(int));
*inicial = 1;
ProcuraProfundidade(raiz, &inicial, posicao, &NodoEncontrado);
return NodoEncontrado;
}
}
int main(int argc, char **argv){
Nodo *raiz, *atual;
int i;
raiz = NULL;
// Cria uma árvore de 7 elementos aleatórios
for (i = 0; i < 7; i++) {
atual = (Nodo*)malloc(sizeof(Nodo));
atual->Esquerda = atual->Direita = NULL;
atual->Elemento = rand();
InsereNodo(&raiz, atual);
}
// Escreve todos os elementos da árvore
printf("Lista de elementos\n----------\n");
ListarEmOrdem(raiz);
// Procura por todas as posições, de 0 a n+1, para cobrir pelo menos 2 casos de erro
printf("\n\nResultado das buscas\n----------\n");
for (i = 0; i <= 8; i++){
atual = Procura(raiz, i);
if (atual)
printf("%d: %d\n", i, atual->Elemento);
else
printf("%d: %p\n", i, atual);
}
return EXIT_SUCCESS;
}
Basically, the search works exactly the same as the writing function, but adds stop conditions to avoid fetching the whole tree when you reach the position you would like.
For control, it uses 2 pointers-to-pointers, so that each sub-call of the function controls the same values. This is the part where I trade a genius algorithm for actually using language tools. It works like a dream!
At the end of the day, the end result is closer than you would naturally imagine:
walk through the tree
for each element add one to the counter
if the meter is equal to the position you want
- return the element
If you want to know more about pointers: http://www.mtm.ufsc.br/~Azeredo/cursoC/aulas/c600.html
I think it would be better to allocate
inicial
on the stack instead of using malloc (you forgot darfree, btw).– hugomg