Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Apuntadores y listas
1. REPÚBLICA BOLIVARIANA DE VENEZUELA MINISTERIO DEL PODER POPULAR PARA LA DEFENSA UNIVERSIDAD NACIONAL EXPERIMENTAL DE LA FUERZA ARMADA NÚCLEO FALCÓN - EXTENSIÓN PUNTO FIJO Apuntadores / Estructura de datos lineales Docente: Licda. Marialix Quintero Punto Fijo, Mayo de 2011
2. Una de las aplicaciones más interesantes y potentes de la memoria dinámica y los punteros son las estructuras dinámicas de datos. Las estructuras básicas disponibles en C y C++ tienen una importante limitación: no pueden cambiar de tamaño durante la ejecución. Los arreglos están compuestos por un determinado número de elementos, número que se decide en la fase de diseño, antes de que el programa ejecutable sea creado. En muchas ocasiones se necesitan estructuras que puedan cambiar de tamaño durante la ejecución del programa. Por supuesto, podemos hacer 'arrays' dinámicos, pero una vez creados, tu tamaño también será fijo, y para hacer que crezcan o diminuyan de tamaño, deberemos reconstruirlas desde el principio, por este motivo los arrays no hacen un uso eficiente de la memoria.
3.
4.
5.
6. Ejemplo: Hacer un programa muestre por pantalla el valor y la dirección de una variable x de tipo entero. #include <stdio.h> void main() { int n = 75; cout<<”el valor de n es: ”<<n; cout<<”la dirección de memoria de n es: ”<<&n; } Ojo: la dirección viene dada en hexadecimal Punteros o apuntadores (Direcciones en memoria)
7. L as variables vistas hasta este momento contienen valores de datos, por el contrario las variables punteros contienen valores que son direcciones de memoria donde se almacenan datos. En resumen, un puntero es una variable que contiene una dirección de memoria, y utilizando punteros su programa puede realizar muchas tareas que no sería posible utilizando tipos de datos estándar. Punteros o apuntadores (Definición) Puntero= variable dirección de memoria dirección de memoria de otra variable = Puntero a punta a otra variable
8. Cuando se telefonea a una persona, se utiliza un puntero (el número de teléfono que se marca). Punteros o apuntadores (Ejemplos) Cuando se envía una carta por correo, su información se entrega basada en un puntero que es la dirección de esa carta. Así pues, una dirección de correos y un número de teléfono tienen en común que ambos indican dónde encontrar algo.
9.
10. Los tipos de datos tienen que corresponderse es decir (declaración de variable de tipo de dato). Los punteros se enlazan a tipos de datos específicos, de modo que C verificará si se asigna la dirección de un tipo de dato al tipo correcto de puntero. Así, por ejemplo, si se define un puntero a float, no se le puede asignar la dirección de un carácter o un entero. Por ejemplo, este segmento de código no funcionará: Ejemplo: float *fp; char c; fp = &c; / * no es válido * / Existen dos operadores especiales de punteros: & y *. El operador de dirección (&) devuelve la dirección de memoria de su operando. El operador de indirección (*) devuelve el contenido de la dirección apuntada por el operando. Punteros o apuntadores (Ventajas y desventajas)
11. Inicialización Ejemplos de Asignación estática de memoria void main(){ int a; int* b; b = &a; //El puntero 'b' apunta a 'a'. } Punteros o apuntadores (Declaración e inicialización) Declaración tipo_de_dato *nombre_var_puntero ej: int *punt; float *nuevo;
12. Existen dos tipos de punteros especiales muy utilizados en el tratamiento de sus programas: los punteros void y null (nulo). Un puntero nulo no apunta a ninguna parte -dato válido- en particular, es decir, «un puntero nulo no direcciona ningún dato válido en memoria». Un puntero nulo se utiliza para proporcionar a un programa un medio de conocer cuando una variable puntero no direcciona a un dato válido. Para declarar un puntero nulo se utiliza la macro NULL, definida en los archivos de cabecera STDEF . H, STDIO. H, STDLIB. H y STRING. H. Se debe incluir uno o más de estos archivos de cabecera antes de que se pueda utilizar la macro NULL. Ejemplos: char *p = NULL; Estático nuevo->sig=NULL; Dinámico En C se puede declarar un puntero de modo que apunte a cualquier tipo de dato, es decir, no se asigna a un tipo de dato específico. En C se puede declarar un puntero de modo que apunte a cualquier tipo de dato, es decir, no se asigna a un tipo de dato específico. El método es declarar el puntero como un puntero void *, denominado puntero genérico. Punteros o apuntadores (Punteros Null y void)
13.
14. Las estructuras dinámicas nos permiten crear estructuras de datos que se adapten a las necesidades reales a las que suelen enfrentarse nuestros programas. Pero no sólo eso, también nos permitirá crear estructuras de datos muy flexibles, ya sea en cuanto al orden, la estructura interna o las relaciones entre los elementos que las componen. Las estructuras de datos están compuestas de otras pequeñas estructuras a las que llamaremos nodos o elementos, que agrupan los datos con los que trabajará nuestro programa y además uno o más punteros autoreferenciales, es decir, punteros a objetos del mismo tipo nodo. Una estructura básica de un nodo para crear listas de datos seria: struct nodo { int dato; struct nodo *sig; }; Listas lineales (Definición)
15.
16.
17.
18. Caso 2: Insertar un elemento en la primera posición de la lista (menor que el 1er elemento) El proceso sigue siendo muy sencillo: Hacemos que nodo->siguiente apunte a Lista. Hacemos que Lista apunte a nodo. Lista simple o abierta (Operaciones con listas) Código: else if (elem<=inicio->dato){ nuevo=new nodo; nuevo->dato=elem; nuevo->sig=inicio; inicio=nuevo; } 10 NULL 5 sig 10 50
19. Caso 3: Insertar un elemento después de un nodo cualquiera de la lista Procedimiento Recorrer la lista e ir guardando el anterior cuando se encuentre la posición correcta, el anterior debe apuntar al nuevo nodo y el nuevo->siguiente a la posición siguiente del anterior. Lista simple o abierta (Operaciones con listas) else { aux=inicio; while (aux!=NULL){ if (elem<aux->dato) break; ant=aux; aux=aux->sig; } nuevo=new nodo; nuevo->dato=elem; ant->sig=nuevo; nuevo->sig=aux; } 10 NULL 5 sig Aux=10-50 Elem=7 Ant=10 7 NULL 10 50 20 5 sig 10 7 sig 20 10 NULL 50
20. Recorrer / Mostrar void mostrar() { nodo *aux; aux=inicio; while(aux!=NULL){ cout<<""<<aux->dato<<""; aux=aux->sig;} aux=lista;} Lista simple o abierta (Operaciones con listas) 5 sig 10 7 sig 20 10 NULL 50
21. Buscar / Eliminar: Se debe recorrer la lista buscando el elemento a borrar, tomando en cuenta su posición en la lista: si es el primer elemento, el último o esta en el medio. void eliminar(int elem) { aux=inicio; while (aux!=NULL){ if (elem==aux->dato) break; ant=aux; aux=aux->sig; }//while if(aux==NULL) cout<<"elemento no encontrado"; else{ if (aux==inicio)//primer elemento inicio=aux->sig; else if (aux->sig==NULL)//ultimo ant->sig=NULL; else ant->sig=aux->sig; delete(aux);} } Lista simple o abierta (Operaciones con listas) 5 sig 10 7 sig 20 10 NULL 50 Aux=10-20 Elem=7 Ant=10
22. Cuerpo del programa Librería: #include <iostream.h> void main(){ int op; while (op<4) { cout<<"Listas Dinamicas - Menu Principal"; cout<<"1.Insertar"; cout<<"2.Eliminar"; cout<<"3.Mostrar"; cout<<”4.Salir"; cout<<"Seleccione una opcion: "; cin>>op; int dat; switch (op){ case 1: { cout<<"Dato: "; cin>>dat; insertar(dat); break; } case 2: { cout<<"Dato: "; cin>>dat; eliminar(dat); break;} case 3:{ mostrar(); break; } } } } Lista simple o abierta (Operaciones con listas)
23.
24.
25. void insertar(){ int dato; nuevo=new nodo; cout<<"Ingrese numero: "; cin>>dato; nuevo->elem=dato; if (inicio==NULL){//lista vacia nuevo->sig=NULL; nuevo->ant=NULL; inicio=nuevo; fin=nuevo; } else if(dato<inicio->elem){//inserto al inicio nuevo->sig=inicio; nuevo->ant=NULL; inicio->ant=nuevo; inicio=nuevo; } else if(dato>fin->elem){//inserto por el final nuevo->ant=fin; nuevo->sig=NULL; fin->sig=nuevo; fin=nuevo; } else{//se recorre la lista aux=inicio; while(aux!=NULL){ if(dato<aux->elem) break; aux=aux->sig; }//while //se enlaza con el siguiente nuevo->sig=aux; nuevo->ant=aux->ant; aux->ant->sig=nuevo; aux->ant=nuevo; } } 5 sig 10 ant 4 Sig 10 20 Ant Null 5 Sig null 10 Ant 20 Inicio Inicio Nuevo-inicio Inicio Inicio Null Nuevo 4 Sig 10 Ant Null 5 Sig 50 Ant 20 20 8 Sig null Ant 10 10 50 6 sig 80 ant Null Inicio Inicio 4 Sig 10 Ant Null 5 Sig 80 Ant 20 20 8 Sig null Ant 80 10 50 8 Sig 50 Ant 10 80 Nuevo
26. void eliminar(){ int dato_eli; cout<<"Ingrese dato a eliminar: "; cin>>dato_eli; aux=inicio; while(aux!=NULL){ if(dato_eli==aux->elem) break; aux=aux->sig; } //se evaluan 4 casos if(aux==NULL){//no encontrado cout<<"elemento no encontrado"; } else if(aux==inicio){//borra el 1er nodo if((aux->sig==NULL) &&(aux->ant==NULL) ){ inicio=NULL; fin=NULL;} else{ inicio=inicio->sig; inicio->ant=NULL;} } else if (aux==fin){//borra el ultimo nodo if((aux->sig==NULL) &&(aux->ant==NULL) ){ inicio=NULL; fin=NULL;}//if else{ fin=fin->ant; fin->sig=NULL;} } else{//cualquier otro nodo aux->ant->sig=aux->sig; aux->sig->ant=aux->ant; } delete(aux); } Inicio Fin 4 Sig 10 Ant Null 5 Sig null Ant 20 20 8 Sig null Ant 10 10 50 Inicio 4 Sig 10 Ant Null 5 Sig 50 Ant null 20 8 Sig null Ant 10 10 50 Fin Inicio 4 Sig 50 Ant Null 5 Sig 50 Ant 20 20 8 Sig null Ant 20 10 50 Fin 4 sig 10 ant Inicio Null
27. void main(){ int opcion; while(opcion<4){ system("cls"); cout<<"1. Insertar"; cout<<"2. Mostrar"; cout<<"3. Eliminar"; cout<<"4. Salir"; cout<<"Seleccione: "; cin>>opcion; switch(opcion){ case 1:{insertar(); break;} case 2: { mostrar(); break;} case 3: {eliminar(); break;} } } }
28.
29. Lista circular (Operaciones con listas) #include <iostream.h> #include <iostream> struct nodo{ int dato; nodo *sig; }*inicio=NULL, *nuevo=NULL, *ant, *aux, *sigue; void insertar() { nuevo=new (nodo); cout<<"Elemento: "; cin>>nuevo->dato; if(inicio==NULL){ inicio=nuevo; nuevo->sig=inicio; }else { ant=inicio; aux=inicio->sig; while(aux!=inicio) {ant=aux; aux=aux->sig;} ant->sig=nuevo; nuevo->sig=inicio; } } 5 Sig 10 10 ant Inicio 5 Sig 20 10 Ant 10 Inicio 4 Sig 10 Ant=10 Aux=10 20
30. void mostrar_circular(){ if(inicio!=NULL){//lista no vacia ant=inicio; aux=inicio->sig; cout<<ant->dato<<""; while((aux!=inicio)&&(aux!=NULL)){ cout<<aux->dato<<""; aux=aux->sig; } } } int contar_nodos(){ int cant=1; ant=inicio; aux=inicio->sig; while(aux!=inicio){ cant++; aux=aux->sig; } return(cant); } 5 Sig 20 10 Ant 10 Inicio 4 Sig 10 Ant=10 Aux=20 20
31. void menu(){ int opcion; while(opcion<4){ system("cls"); cout<<"1. Insertar"; cout<<"2. Mostrar"; cout<<"3. Contar Nodos"; cout<<"4. Salir"; cout<<"Seleccione: "; cin>>opcion; switch(opcion){ case 1:{insertar(); break;} case 2: { mostrar_circular(); break;} case 3: { cout<<"La lista tiene: "<<contar_nodos()<<" nodos"; break;} } } } void main(){ menu(); }
32. Hacer un programa que almacene en una Lista Circular, la nota definitiva de 10 alumnos de lenguajes de programación, y muestre la nota más alta y el promedio de la sección. Lista circular (Operaciones con listas)