Foro: Dudas y Consultas

TPN3 consulta

TPN3 consulta

de Usuario eliminado -
Número de respuestas: 2

Buenas profe, queria saber si lo que desarrolle seria correcto:

2_ a_

typedef struct treg{
int num;
bool prim;
int dig;
};
typedef struct tnodo *pnodo;
typedef struct tnodo {
treg dato;
pnodo ant;
pnodo sig;
};
 //si vas a usar un único puntero establecer un registro tlista es incorrecto, sólo se usa un registro si tienes al menos 2 campos que representan la lista, como un puntero y un contador por ejemplo, eso hace que debas cambiar las operaciones

typedef struct tlista

pnodo inicio;
};
main(){
tlista lista; //aquí debería ser directamente pnodo lista, ya que sólo tiene un puntero no corresponde el registro
pnodo nuevo;
}

b_

void agregar_final(tlista &lista, pnodo nuevo){ //debes trabajar con pnodo &lista
pnodo i;
if(lista.inicio==NULL){
lista.inicio=nuevo;
}else{
for(i=lista.inicio;i->sig!=NULL;i=i->sig);
if(nuevo->dato.num==i->dato.num-1 && nuevo->dato.prim==true){//cuál es el objetivo de la condición que está en azul?

si por ejemplo el último nodo fuese 7 y el nuevo valor 13 preguntaría 13==8 (incluso provoca error y permite guardar 2 primos de manera consecutiva)

cout<<"No se puede agregar, no cumple con lo requerido"<<endl;
delete(nuevo);
}else{
i->sig=nuevo;
nuevo->ant=i;
}
}
}

c_

pnodo mayor_primo(tlista lista){//debes trabajar con pnodo
pnodo mayor,i;
if(lista.inicio==NULL)
mayor=NULL;
else{
mayor=lista.inicio;
for(i=lista.inicio->sig;i!=NULL;i=i->sig){ //la lógica es correcta, pero debes trabajar con pnodo y no con tlista
if((i->dato.num > mayor->dato.num) && i->dato.prim==true)
mayor=i;
}
}
return mayor;
}

d_válido, se podría optimizar si consideras que el parámetro de opción lo recibe el módulo que muestra y en base a eso realiza el recorrido que corresponde.

void submenu(char &op){
cout<<"***Menu***"<<endl;
cout<<"1_Inicio"<<endl;
cout<<"2_Final"<<endl;
cout<<"Elija una opcion"<<endl;
cin>>op;
}
void mostrar_lista_op(tlista lista){
char op;
if(lista.inicio != NULL){
submenu(op);
switch(op){
case '1': mostrar_lista1(lista);
break;
case '2': mostrar_lista2(lista);
break;
}
}else
cout<<"LISTA VACIA";
}
void mostrar_lista1(tlista lista){
pnodo i;
for(i=lista.inicio;i!=NULL;i=i->sig)
if(i->dato.prim==true)
cout<<"Nodo: "<<i->dato.num<<" dig: "<<i->dato.dig<<" Es Primo"<<endl;
else
cout<<"Nodo: "<<i->dato.num<<" dig: "<<i->dato.dig<<" NO es Primo"<<endl;
}
void mostrar_lista2(tlista lista){
pnodo i,j;
for(i=lista.inicio;i->sig!=NULL;i=i->sig);
for(j=i;j!=NULL;j=j->ant)
cout<<"Nodo: "<<j->dato.num<<endl;
}

3_a_válido

const int MAX=10;

typedef struct tnodo *pnodo;
typedef struct tnodo {
char dato;
pnodo ant;
pnodo sig;
};
typedef struct tlista{
pnodo inicio;
pnodo fin;
int cont;
};
main(){
tlista lista;
pnodo nuevo;
}

b_//válido

void agregar_final(tlista &lista, pnodo nuevo){
if(lista.cont!=MAX){
if(lista.inicio==NULL){
lista.inicio=nuevo;
lista.fin=nuevo;
}else{
lista.fin->sig=nuevo;
nuevo->ant=lista.fin;
lista.fin=nuevo;
}
lista.cont++;
}else{
cout<<"No se puede agregar mas nodos"<<endl;
delete(nuevo);
}
}

4_a_

typedef struct tnodo *pnodo;
typedef struct tnodo {
int dato;
pnodo ant;
pnodo sig;
};
typedef struct tlista{//no debe usarse un registro para un único campo, se debería trabajar directamente con pnodo

cuidado!!, esto obliga a cambiar todas las operaciones para considerarse correctas

pnodo inicio;
};
main(){
tlista lista,lista2,lista3; deberías se pnodo y no tlista
}

b_ //aquí deberías tener una operación que cargue una lista y luego invocarla 2 a fin de no repetir código

void agregar(tlista &lista, tlista &lista2){
char resp;
int valor;
pnodo nuevo;
cout<<"Lista 1"<<endl;
do{
cout<<"Ingrese valor: ";
cin>>valor;
crear_nodo(nuevo,valor);
if(nuevo!=NULL)
agregar_orden(lista,nuevo);
else
cout<<"Memoria Llena"<<endl;
cout<<"Desea agregar otro valor (s/n)? : ";
cin>>resp;
} while(resp!='n');
cout<<"Lista 2"<<endl;
do{
cout<<"Ingrese valor: ";
cin>>valor;
crear_nodo(nuevo,valor);
if(nuevo!=NULL)
agregar_orden(lista2,nuevo);
else
cout<<"Memoria Llena"<<endl;
cout<<"Desea agregar otro valor (s/n)? : ";
cin>>resp;
} while(resp!='n');
}

void agregar_orden(tlista &lista, pnodo nuevo){//debes adaptar a una lista de tipo pnodo
pnodo i;
if(lista.inicio==NULL){
lista.inicio=nuevo;
}else{
if(nuevo->dato <= lista.inicio->dato){
nuevo->sig=lista.inicio;
lista.inicio->ant=nuevo;
lista.inicio=nuevo;
}else{
for(i=lista.inicio;i->sig!=NULL && (i->sig)->dato < nuevo->dato;i=i->sig);
if(i->sig==NULL){
i->sig=nuevo;
nuevo->ant=i;
}else{
nuevo->sig=i->sig;
nuevo->ant=i;
(i->sig)->ant=nuevo;
i->sig=nuevo;
}
}
}
}

(cargar valores aleatorios)//aquí la carga también debería hacerse por separada cada lista, un módulo de carga invocado dos veces

void agregar(tlista &lista, tlista &lista2){
int valor,cant;
pnodo nuevo;
cout<<"Lista 1"<<endl;
cout<<"Indique la cantidad a ingresar: ";
cin>>cant;
do{
valor=rand()%90+10;
crear_nodo(nuevo,valor);
if(nuevo!=NULL)
agregar_orden(lista,nuevo);
else
cout<<"Memoria Llena"<<endl;
cant--;
} while(cant>0);
cout<<"Lista 2"<<endl;
cout<<"Indique la cantidad a ingresar: ";
cin>>cant;
do{
valor=rand()%90+10;
crear_nodo(nuevo,valor);
if(nuevo!=NULL)
agregar_orden(lista2,nuevo);
else
cout<<"Memoria Llena"<<endl;
cant--;
} while(cant>0);
}

5_a_

typedef struct tnodo *pnodo;
typedef struct tnodo {
int dato;
pnodo ant;
pnodo sig;
};
typedef struct tlista{//no corresponde si sólo se tiene un puntero
pnodo inicio;
};

main(){
tlista lista;debería ser pnodo y no tlista
pnodo nuevo;
}

b_

void agregar_orden(tlista &lista, pnodo nuevo){l//lista debería ser pnodo
pnodo i;
if(lista.inicio==NULL){
lista.inicio=nuevo;
lista.inicio->sig=lista.inicio;
lista.inicio->ant=lista.inicio;
}else{
if(nuevo->dato <= lista.inicio->dato){
nuevo->sig=lista.inicio;
lista.inicio->ant=nuevo;
for(i=lista.inicio;i->sig!=lista.inicio;i=i->sig);
nuevo->ant=i;
i->sig=nuevo;
lista.inicio=nuevo;
}else{
for(i=lista.inicio;i->sig!=lista.inicio && (i->sig)->dato < nuevo->dato;i=i->sig);
if(i->sig==lista.inicio){//estos casos podrían unificarse al tratarse de una lista doble circular con un único puntero
i->sig=nuevo;
nuevo->ant=i;
nuevo->sig=lista.inicio;
lista.inicio->ant=nuevo;
}else{ //este intercambio de punteros sirve para cuando se agrega en medio o al final para este planteo
nuevo->sig=i->sig;//si fuese al final este engancha el nuevo con el inicio
nuevo->ant=i; //este el nuevo con el último
(i->sig)->ant=nuevo;//el inicio con el nuevo
i->sig=nuevo;//el final con el nuevo
}
}
}
}
pnodo quitar_nodo_espe(tlista &lista, int borrado){//debes trabajar con pnodo para lista
pnodo i, extraido;
if(lista.inicio==NULL)
extraido=NULL;
else{
if(lista.inicio->dato==borrado){
if(lista.inicio->sig==lista.inicio){
extraido=lista.inicio;
lista.inicio=NULL;
extraido->sig=NULL;
extraido->ant=NULL;
}else{
for(i=lista.inicio;i->sig!=lista.inicio;i=i->sig);
extraido=lista.inicio;
lista.inicio=extraido->sig;
i->sig=lista.inicio;
i->ant=lista.inicio;//este debería ser inicio->ant=i;
extraido->sig=NULL;
extraido->ant=NULL;
}
}else{
for(i=lista.inicio;i->sig!=lista.inicio && (i->sig)->dato != borrado; i=i->sig);
if((i->sig)->dato==borrado){
extraido=i->sig;
i->sig=extraido->sig;
(extraido->sig)->ant=i;
extraido->sig=NULL;
extraido->ant=NULL;

}else
extraido=NULL;
}
}
return extraido;
}

bool buscar_nodo(tlista lista, int valor){
bool encontrado=false;
pnodo i;
for(i=lista.inicio;i->sig!=lista.inicio && valor>i->dato && encontrado==false;i=i->sig);//esto funciona si la lista está ordenada, si no podría preguntar por != en lugar de mayor
if(valor==i->dato)
encontrado=true;
return encontrado;
}

c_//válida la lógica pero debe trabajar con lista de tipo pnodo ya que la definición no es válida

int contar_nodo_impar(pnodo list, tlista lista){
int c;
if(list->sig==lista.inicio)
c=0;
else{
if((list->dato)%2!=0)
c=1+contar_nodo_impar(list->sig,lista);
else
c=contar_nodo_impar(list->sig,lista);
}
return c;
}

símil al anterior, lógica válida pero debe corregir la definición de la estructura para que se considere el ejercicio
int sumar_nodos(pnodo i, tlista lista){
if(i->sig==lista.inicio)
return i->dato;
else
return i->dato + sumar_nodos(i->sig,lista);
}

void mostrar_lista(tlista lista,pnodo n, char op1){debe trabajar con pnodo lista
if(lista.inicio == NULL)
cout<<"Lista vacia"<<endl;
else{
if(n->sig==lista.inicio)
cout<<n->dato<<endl;
else{
if(op1=='1'){
cout<<n->dato<<endl;
mostrar_lista(lista,n->sig,op1);
}else{
if(op1=='2'){
mostrar_lista(lista,n->sig,op1);
cout<<n->dato<<endl;
}
}
}
}
}

6_ (circulares)

void agregar_inicio(tlista &lista, pnodo nuevo){//circular
if(lista.contador!=MAX){
if(lista.inicio==NULL){
lista.inicio=nuevo;
lista.fin=nuevo;
}else{
nuevo->vecino[0]=lista.inicio;//recomendación siempre marcar la consideración que tienen posición 0 siguiente, posición 1 anterior por ejemplo
lista.inicio->vecino[1]=nuevo;
lista.inicio=nuevo;
}
lista.fin->vecino[0]=lista.inicio;
lista.inicio->vecino[1]=lista.fin;
lista.contador++;
}else{
cout<<"Superaste el limite"<<endl;
delete(nuevo);
}
}

pnodo quitar_final(tlista &lista){ //circular
pnodo extraido;
if(lista.inicio==NULL){
extraido=NULL;
}else{
extraido=lista.fin;
if(lista.inicio==lista.fin){
iniciar_lista(lista);
}else{
lista.fin=lista.fin->vecino[1];//apunta al anterior considerando que 1 es ant
lista.inicio->vecino[1]=lista.fin; 
lista.fin->vecino[0]=lista.inicio;
lista.contador--;
}
extraido->vecino[0]=NULL;
extraido->vecino[1]=NULL;
}
return extraido;
}

void mostrar_lista(tlista lista){válido
pnodo i;
if(lista.contador==0)
cout<<"Lista Vacia"<<endl;
else{
i=lista.inicio;
while(i->vecino[0]!=lista.inicio){
cout<< i->dato <<endl;
i=i->vecino[0];
}
cout<< i->dato <<endl;
}
}

Saludos

(Editado por Verónica Torres - envío original viernes, 8 de septiembre de 2023, 00:41)

En respuesta a Usuario eliminado

Re: TPN3 consulta

de Verónica Torres -
Hola Francisco, la lógica en su mayor parte es correcta, sin embargo las definiciones de estructuras no son válidas en todos los puntos, ten presente que cuando defines un registro de tipo tlista para tu lista, sólo tiene sentido si necesitas al menos dos elementos que la representes por ejemplo un puntero y un contador, o dos punteros, o dos punteros y un contador, etc. Cuando sólo se pide un único puntero sin dato adicional, entonces se trabaja directamente con una lista de tipo pnodo y no tlista.
Ten presente esto ya que te invalidaría un punto en el parcial, si la definición de la estructura es incorrecta ya no se corrige las operaciones.
saludos
En respuesta a Verónica Torres

Re: TPN3 consulta

de Usuario eliminado -

Muchas gracias profe, ya hice las correcciones en las estructuras.

Este lo hice mal, revise otra vez el ejercicio y yo interprete otra cosa, 

void agregar_final(tlista &lista, pnodo nuevo){ //debes trabajar con pnodo &lista
pnodo i;
if(lista.inicio==NULL){
lista.inicio=nuevo;
}else{
for(i=lista.inicio;i->sig!=NULL;i=i->sig);
if(nuevo->dato.num==i->dato.num-1 && nuevo->dato.prim==true){//cuál es el objetivo de la condición que está en azul?

si por ejemplo el último nodo fuese 7 y el nuevo valor 13 preguntaría 13==8 (incluso provoca error y permite guardar 2 primos de manera consecutiva)

cout<<"No se puede agregar, no cumple con lo requerido"<<endl;
delete(nuevo);
}else{
i->sig=nuevo;
nuevo->ant=i;
}
}
}

Pero a que se refiere con no podrán almacenarse números primos en nodos consecutivos, osea la parte de los nodos consecutivos?

 

Despues el contar valores impares del punto 5, no me toma el ultimo como podria hacer:

int contar_nodo_impar(pnodo list,pnodo inicio){  
int c;
if(list->sig==inicio)
c=0;
else{
if((list->dato)%2!=0)
c=1+contar_nodo_impar(list->sig,inicio);
else
c=contar_nodo_impar(list->sig,inicio);
}
return c;
}