Me podrian ayudar!!!!!! caracteres por cadenas?? y contar nodos con recursion???

Iniciado por Principios en C, 5 Noviembre 2011, 19:51 PM

0 Miembros y 1 Visitante están viendo este tema.

Principios en C

Hola..

Tengo un codigo que hice el cual crea y ordena en forma alfabeticamente creciente un lista de caracteres, se pueden insertar elementos a la lista y eliminarlos.

Pero me falta dos puntos para terminar mi programa:

1° tengo que imprimir con una función recursiva la lista ordenada alfabeticamente decreciente, es decir de z-a,.

2° Y hacer una funcion recursiva que al momento que yo ingrese un elemeto que quiero que se busque en la lista me diga cuantos caracteres hay antes y cuantes después del caracter que yo indique.

Aqui esta mi codigo, pero quisiera ver si me ayudan y me pueden decir como hacer estas dos funciones recursivas que me faltan, por favor:


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

struct lista_nodos {
     
      /*Se declara una estructura*/
     
      char valor;
      struct lista_nodos *sigPtr; };
     
      typedef struct lista_nodos LISTA;
      typedef struct lista_nodos *LISTPREVPTR;
      /*Se usa un alias para la estructura lista_nodos*/
     
      void inserta(LISTPREVPTR*, char);
      /*Se declara la función inserta*/
      char elimina (LISTPREVPTR*, char);
      /*Se declara la función elimina*/
      int estavacia (LISTPREVPTR);
      /*Se declara la función estavacia*/
      void imprime (LISTPREVPTR);
      /*Se declara la función imprime*/
      void menu (void);
      /*Se declara la funcion menu*/
     
      main(){
             
      LISTPREVPTR inicioPtr = NULL;
      int avanza, selec;
      char dato;
      printf("\n\n%s\n\n","<Un programa que construye listas dinamicas>");
      menu();
      /*Se manda llamar a la función menu*/
      printf("\n%s","\n\nLa opción seleccionada es: ");
      scanf("%d",&selec);
      /*Se lee la función que elige el usuario*/
     
      while(selec != 3){
      /*Cuando la opción elegida por el usuario sea distinta de 1, 2 o 3
      se despliega nuevamente el menu*/
                 
      switch(selec){
      /*Se definen las acciones a realizar conforme a la opción que elija
      el usuario*/
                   
      case 1:
     
      printf("\n%s","Deme un caracter: ");
      scanf("\n%c", &dato);
      inserta(&inicioPtr, dato);
      /*Se manda llamar a la funcón inserta*/
      imprime(inicioPtr);
      /*Se manda llamar a la función inicio*/
      break;
     
      case 2:
           
      if(!estavacia(inicioPtr)){
                             
      printf("\n%s","El caracter a eliminar es: ");
      scanf("\n%c",&dato);
     
      if(elimina(&inicioPtr, dato)){
      /*Se manda llamar a la función elimina*/
     
      printf("\n%s%c%s\n\a\a","El caracter: ",dato,"fue eliminado de la lista");
      imprime(inicioPtr);
      /*Se manda llamar a la función imprime*/
      }
      else
      /*En caso de no encontrarse el caracter se entra al else*/
     
   printf("\n%s%c%s\n\a","El caracter: ",dato,"no fue encontrado en la lista");
   }
   
      else
      /*La ultima opcion que puede ocurrir al momento de eliminar un carcter
      se presenta en este else*/
      printf("\a\n\t%s\n\a","La lista esta vacia");
      break;
     
      default:
      /*En caso de no ocurrir nada de lo anterior se lanzara en pantalla
      lo siguiente*/
     
      printf("\n%s\n","La selección es incorrecta");
      menu();
      /*Se despliega el menu*/
      break;
      }
     
      menu();
      printf("\n%s","La opcion seleccionada es: ");
      scanf("%d", &selec);
      };
     
      printf("\n\n%s","Hasta pronto");
      scanf("%d",&avanza);
      return 0;
      }
     
      void menu(void){
      /*Se define la función menu*/
           
      printf("\n\nSeleccione una opcion: ");
      printf("\n\n1.-Insertar un elemento en la lista");
      printf("\n\n2.-Eliminar un elemento en la lista");
      printf("\n\n3.-Salir del programa");
      }
     
      void inserta(LISTPREVPTR*aPtr, char datoin){
      /*Se define la función inserta*/
      LISTPREVPTR datnvoPtr, datprevPtr, datactPtr, lista_nodos;
      /*Se declaran apuntadores que sean del tipo LISTPREVPTR*/
      datnvoPtr=(LISTPREVPTR)malloc(sizeof(lista_nodos));
      /*evalúa a sizeof (lista_nodos) para determinar el tamaño de una
      estructura del tipo lista_nodos, para asignar una nueva área en
      memoria, y para almacenar un apuntador a la memoria asignada a la
       variable datnvoPtr */
     
      if(datnvoPtr != NULL){
      /*En caso de que datnvoPtr sea distinto de NULL, se realizara lo
      siguiente*/
                   
      datnvoPtr->valor=datoin;
      datnvoPtr->sigPtr=NULL;
      datprevPtr=NULL;
      datactPtr=*aPtr;
     
      while(datactPtr != NULL&&datoin>datactPtr->valor){
     
      datprevPtr=datactPtr;
      datactPtr=datactPtr->sigPtr;
      };
     
      if(datprevPtr==NULL){
      /*Se compara datprevPtr con NULL y se continuara si son iguales*/
      datnvoPtr->sigPtr=*aPtr;
      *aPtr=datnvoPtr;
      }
     
      else{
      /*Si datprevPtr es distinto de NULL se entrara al else*/
      datprevPtr->sigPtr=datnvoPtr;
      datprevPtr->sigPtr=datactPtr;
      }
      }
     
      else
      /*En caso de no haber ocurrido ninguna de las anteriores se entrara
      a este else*/
      printf("\n%s%c%s\n%s\a\a\a\a","El caracter: ",datoin,"no fue insertado",
      "memoria insuficiente\n\n");
      }
     
      char elimina(LISTPREVPTR*bPtr, char datoele){
      /*Se define la función elimina*/
           
      LISTPREVPTR datempPtr, datprevPtr, datactPtr;
      /*Se declaran apuntadores que sean dell tipo LISTPREVPTR*/
     
      if(datoele==(*bPtr)->valor){
      datempPtr=*bPtr;
      *bPtr=(*bPtr)->sigPtr;
      free(datempPtr);
      /*Se liberara memoria de datempPtr*/
      return datoele;
      }
     
      else{
      datprevPtr=*bPtr;
      datactPtr=(*bPtr)->sigPtr;
     
      while(datactPtr!=NULL&&datactPtr->valor!=datoele){
      datprevPtr=datactPtr;
      datactPtr=datactPtr->sigPtr;
      };
     
      if(datactPtr!=NULL){
      datempPtr=datactPtr;
      datprevPtr->sigPtr=datactPtr->sigPtr;
      free(datempPtr);
      /*Se liberara memoria de datempPtr*/
      return datoele;
      }
      }
      return '\0';
      }
     
      int estavacia(LISTPREVPTR cPtr){
      /*Se define la función estavacia*/
         
      return(cPtr==NULL);
      }
     
      void imprime(LISTPREVPTR dPtr){
      /*Se define la función imprime*/
           
      if(dPtr==NULL){
      /*En casao de que dPtr no este inicializado se imprimira lo de abajo*/
                     
      printf("\a\n\t%s","La lista esta vacia\n\n");
      printf("NULL \n\n");
      }
     
      else{
      /*Cuando dPtr tenga valor se mostrara la lista*/
      printf("\n\t%s","La lista es: ");
      while(dPtr!=NULL){
      /*Solo cuando dPtr sea distitno de NULL se hara la impresión que aparece
      abajo*/
      printf("%c--->",dPtr->valor);
      dPtr=dPtr->sigPtr;
      }
      printf("\n");
      }
      }

rir3760

En el primer punto te piden que imprimas la lista en orden inverso, para ello basta con:
void imprimir_inv(struct lista_nodos *p)
{
    if (p != NULL){
        imprimir_inv(p->sigPtr);
        printf("valor == %c\n", p->valor);
    }
}


Para la segunda función debes indicar los requisitos de esta con relación al numero de nodos antes y después del nodo a buscar.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Principios en C

Cita de: rir3760 en  6 Noviembre 2011, 01:44 AM
Para la segunda función debes indicar los requisitos de esta con relación al numero de nodos antes y después del nodo a buscar.

Hola, gracias por responder y ayudarme ... mi duda con lo que estas diciendo y que ya tenia por eso no he podido terminar mi programa es como con una función RECURSIVA (al igual que me piden en el primer punto) hacer que me de el numero de caracteres antes y depués del que pida el usuario.

Por ejemplo si el usuario ingreso las letras: h,o,a,c,l t, p, f, k. Entonces la lista apareceria asi:

a--c--f--h--k--l--o--p--t

y si el usuario quiera saber cuantas lestras hay antes y despues de la "k", aqui seria facil porque es numerable pero en caso de que se ingresen mucho más? sé que ese es el chiste de la recursión, pero no entiendo como hacerlo?

Principios en C

Me surge una duda mas, como le haria para que en lugar de ingresar caracteres pueda ingresar cadenas y en la opcion de eliminar me elimine palabra por palabra y aparte me las ordene alfabeticamente???

Es que esto lo quise hacer modificando algunas cosas pero sigue sin aceptarme cadenas nada mas me lee el primer caracter de la cadena que ingreso.

rir3760

Te respondo al MP:

Los datos en el programa aparecen desordenados en el programa porque este ... no los ordena. Para ello necesitas de una función mas que ordene los nodos de la lista. En el caso de listas vinculadas lo usual es MergeSort pero si apenas empiezas es mejor la ordenación al insertar cada nodo.

En cuanto a la función que imprima el numero de caracteres antes de uno dado debes descomponer eso también en funciones: una que imprima el resultado y otra que calcule el numero de caracteres antes del buscado.

Y faltan los requisitos de la(s) funcion(es). Sin eso difícil dar una respuesta exacta.

No voy a hacerlo todo. En el caso del calculo de forma recursiva del numero de elementos antes de uno dado ello se puede realizar de esta forma:
struct nodo {
    char valor;
    struct nodo *sig;
};

/* ... */

struct nodo *nodos_antes(struct nodo *p, int *num, char ch);

/* ... */

void imprimir_na(struct nodo *p, char ch)
{
    int num = 0;
   
    if (nodos_antes(p, &num, ch) == NULL)
        puts("El caracter no es parte de la lista");
    else
        printf("Hay %d elementos antes del caracter %c\n", num, ch);
}

struct nodo *nodos_antes(struct nodo *p, int *num, char ch)
{
    if (p == NULL || p->valor == ch)
        return p;
    else {
        ++*num;
        return nodos_antes(p->sig, num, ch);
    }
}

Es una función de soporte "imprimir_na" que imprime el resultado de la otra función recursiva "nodos_antes".

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Principios en C

#5
Gracias!!! Pero si los ordena de la a la z... ya lo ejecute varias veces.

Lo que no ordena es la función imprimir_inv que me hiciste favor de proporcionar..
y que la verdad aunque me ayudaste con esa para darme la idea trate de convertila a funcion recursiva y no me salio tampoco

La funcion imprimir_na es independiente de la que ya tengo que es imprime??

Yo sé que es abusar de tu ayuda pero.. es que tengo un buen de tarea y me falta saber como hacer el programa que publique con cadenas??

En el codigo que pusiste arribo ya vez que hay partes en las que hace falta algo y las pones como /*... */, que deberia anexar ahi???
Y en que momento mando llamar a la función???

Perdon, es que estoy super perdido con esto...  :(


rir3760

Cita de: Principios en C en  7 Noviembre 2011, 02:28 AMPero si los ordena de la a la z... ya lo ejecute varias veces.
Tienes razón. Lo siento.

El programa tiene errores en la función "insertar", demasiado larga en mi opinión y si tratas de insertar los caracteres 'a', 'b' y 'c' en ese orden todos menos el primero se pierden, revisala.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Principios en C

#7
Lo sé, es que me cuestan mucho trabajo los punteros... y talvez me complique demasiado la vida pero ya no tengo mucho tiempo para simplificarla y la verdad ya me hice bolas...  

disculpa mi insistencia pero me podrias decir donde mado llamar a la función para contar los nodos?? y sabras como puedo hacer esto con cadenas???

Porfa!!!!!!!!!!!

Principios en C

Cita de: rir3760 en  7 Noviembre 2011, 02:21 AM
Te respondo al MP:

Los datos en el programa aparecen desordenados en el programa porque este ... no los ordena. Para ello necesitas de una función mas que ordene los nodos de la lista. En el caso de listas vinculadas lo usual es MergeSort pero si apenas empiezas es mejor la ordenación al insertar cada nodo.

En cuanto a la función que imprima el numero de caracteres antes de uno dado debes descomponer eso también en funciones: una que imprima el resultado y otra que calcule el numero de caracteres antes del buscado.

Y faltan los requisitos de la(s) funcion(es). Sin eso difícil dar una respuesta exacta.

No voy a hacerlo todo. En el caso del calculo de forma recursiva del numero de elementos antes de uno dado ello se puede realizar de esta forma:
struct nodo {
    char valor;
    struct nodo *sig;
};

/* ... */

struct nodo *nodos_antes(struct nodo *p, int *num, char ch);

/* ... */

void imprimir_na(struct nodo *p, char ch)
{
    int num = 0;
   
    if (nodos_antes(p, &num, ch) == NULL)
        puts("El caracter no es parte de la lista");
    else
        printf("Hay %d elementos antes del caracter %c\n", num, ch);
}

struct nodo *nodos_antes(struct nodo *p, int *num, char ch)
{
    if (p == NULL || p->valor == ch)
        return p;
    else {
        ++*num;
        return nodos_antes(p->sig, num, ch);
    }
}

Es una función de soporte "imprimir_na" que imprime el resultado de la otra función recursiva "nodos_antes".

Un saludo

Me pueden ayudar diciendome como mando llamar esta función en el programa...
Ya me he roto la cabeza y no puedo... :-(