Apuntadores y listas
Upcoming SlideShare
Loading in...5
×
 

Apuntadores y listas

on

  • 5,146 views

En esta presentación se desarrollarán temas relacionados a apuntadores, listas (simples, circulares y doble) y por último una antesala a la pila

En esta presentación se desarrollarán temas relacionados a apuntadores, listas (simples, circulares y doble) y por último una antesala a la pila

Statistics

Views

Total Views
5,146
Views on SlideShare
4,789
Embed Views
357

Actions

Likes
1
Downloads
135
Comments
0

7 Embeds 357

http://lenguajeyprogramacion1.blogspot.com 267
http://lenguajeyprogramacion1.blogspot.mx 64
http://www.lenguajeyprogramacion1.blogspot.com 11
http://lenguajeyprogramacion1.blogspot.com.ar 8
http://lenguajeyprogramacion1.blogspot.com.es 3
https://lenguajeyprogramacion1.blogspot.com 3
http://www.lenguajeyprogramacion1.blogspot.mx 1
More...

Accessibility

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Apuntadores y listas Apuntadores y listas Presentation Transcript

  • 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
  • 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.
  • OBJETIVOS
    • Entender la eficacia del manejo de la memoria dinámica a través del uso de apuntadores
    • Lograr un uso eficiente de las estructuras de datos lineales.
      • Definición.
      • Ventajas y desventajas.
      • Declaración / Inicialización
      • Punteros NULL y void
    Punteros o apuntadores
  • Punteros o apuntadores (Direcciones en memoria)
    • El proceso de asignación dinámica de memoria permite crear y destruir variables en tiempo de ejecución (variables dinámicas). Cuando una variable se declara, se asocian tres atributos fundamentales con la misma: su nombre, su tipo y su dirección en memoria.
    • Ejemplo:
    • int n;
    • / * asocia al nombre n, el tipo int y la dirección de alguna posición de memoria donde se almacena el valor de n* /
    • Al valor de una variable se accede por medio de su nombre.
    • Por ejemplo, se puede imprimir el valor de n con la sentencia: cout<<n;
    • A la dirección de la variable se accede por medio del operador de dirección &.
    • Por ejemplo, se puede imprimir la dirección de n con la sentencia: cout<<&n;
    Ox4f f fd34 n int
  • 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)
  • 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
  • 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.
  • Punteros o apuntadores (Ventajas y desventajas)
    • Los punteros tienen una gran utilidad, pues permiten una programación eficaz a nivel de máquina cuando se maneja la memoria del ordenador.
    • Permiten realizar operaciones de asignación dinámica de memoria.
    • Permiten efectuar operaciones con estructuras de datos dinámicas.
    Ventajas Los punteros deben usarse con precaución, ya que pueden provocar fallos en el programa difíciles de localizar, puede ser por asignación incorrecta de dirección.   Desventajas
  • 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)
  • 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;
  • 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)
      • Definición.
      • Tipos de listas.
      • Operaciones con listas.
    Listas lineales
  • 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)
  • Tipos de listas Simples Circulares Doble
    • El último elemento tiene que apuntar NULL.
    • En las listas hay un nodo especial que es el primero ya que guarda el inicio de la lista y a través de ese nodo se puede recorrer la lista.
    • Si el nodo inicial es NULL indica que la lista está vacia.
    • Es una colección o secuencia de elementos dispuestos uno detrás de otro, en la que cada elemento se conecta al siguiente elemento por un «enlace» o «puntero».
    • La idea básica consiste en construir una lista cuyos elementos llamados nodos se componen de dos partes o campos: la primera parte o campo contiene la información y la segunda parte el puntero que guarda la dirección de memoria del siguiente nodo de la lista o valdrá NULL si es el último elemento.
    • En las listas abiertas existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo la cabeza de la lista. Eso es porque mediante ese único puntero podemos acceder a toda la lista. Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está vacía. “LAS LISTAS SON ORDENADAS”
    Lista simple o abierta
            • Declaración:
            • struct nodo{
            • int dato;
            • struct nodo *siguiente;
            • } *nuevo,*aux,*ant, *inicio=NULL;
    Lista simple o abierta (Operaciones con listas) Inicialización: inicio=NULL; Insertar Caso 1: Lista Vacía El proceso es muy simple, bastará con comprobar si la lista==NULL: nuevo->siguiente apunte a NULL. Lista apunte a nuevo. Código if (inicio==NULL){ nuevo=new nodo; nuevo->dato=elem; nuevo->sig=NULL; inicio=nuevo; } 10 NULL
  • 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
  • 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
  • Recorrer / Mostrar void mostrar() { nodo *aux; aux=inicio; while(aux!=NULL){ cout<<&quot;t&quot;<<aux->dato<<&quot;n&quot;; aux=aux->sig;} aux=lista;} Lista simple o abierta (Operaciones con listas) 5 sig 10 7 sig 20 10 NULL 50
  • 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<<&quot;elemento no encontradon&quot;; 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
  • Cuerpo del programa Librería: #include <iostream.h> void main(){ int op; while (op<4) { cout<<&quot;Listas Dinamicas - Menu Principalnn&quot;; cout<<&quot;1.Insertarn&quot;; cout<<&quot;2.Eliminarn&quot;; cout<<&quot;3.Mostrarn&quot;; cout<<”4.Salirnn&quot;; cout<<&quot;Seleccione una opcion: &quot;; cin>>op; int dat; switch (op){ case 1: { cout<<&quot;Dato: &quot;; cin>>dat; insertar(dat); break; } case 2: { cout<<&quot;Dato: &quot;; cin>>dat; eliminar(dat); break;} case 3:{ mostrar(); break; } } } } Lista simple o abierta (Operaciones con listas)
  • Ejercicios propuestos de listas simple
    • Escribir una función que imprima el número de nodos de una lista simple.
    • Escribir una función que elimine el nodo que ocupa la posición i (dada por el usuario) de una lista simple, siendo el nodo inicio que ocupa la posición n°1.
    • Escribir una función que no permita insertar datos no repetidos.
            • Declaración:
            • struct nodo{
            • int elem;
            • nodo *sig;
            • nodo *ant;
            • }*inicio=NULL, *fin=NULL, *aux, *nuevo;
    Lista doble (Operaciones con listas) 5 sig 10 ant void mostrar(){ aux=inicio; if (aux==NULL) cout<<&quot;nLista Vacia&quot;; while(aux!=NULL){ cout<<aux->elem<<&quot;t&quot;; aux=aux->sig; } } 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
  • void insertar(){ int dato; nuevo=new nodo; cout<<&quot;Ingrese numero: &quot;; 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
  • void eliminar(){ int dato_eli; cout<<&quot;Ingrese dato a eliminar: &quot;; 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<<&quot;elemento no encontradon&quot;; } 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
  • void main(){ int opcion; while(opcion<4){ system(&quot;cls&quot;); cout<<&quot;n1. Insertarn&quot;; cout<<&quot;2. Mostrarn&quot;; cout<<&quot;3. Eliminarn&quot;; cout<<&quot;4. Salirn&quot;; cout<<&quot;Seleccione: &quot;; cin>>opcion; switch(opcion){ case 1:{insertar(); break;} case 2: { mostrar(); break;} case 3: {eliminar(); break;} } } }
  • Lista doble (Operaciones con listas) Ejercicios
    • Utilizar una lista doblemente enlazada para controlar una lista de pasajeros de una línea aérea. El programa principal debe ser controlado por menú y permitir al usuario visualizar los datos de un pasajero determinado (cedula, nombre, apellido, destino), insertar un nodo , eliminar un pasajero de la lista.
    • Crear una lista doble con las edades de 10 personas y una función que calcule el promedio
  • 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<<&quot;Elemento: &quot;; 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
  • void mostrar_circular(){ if(inicio!=NULL){//lista no vacia ant=inicio; aux=inicio->sig; cout<<ant->dato<<&quot;n&quot;; while((aux!=inicio)&&(aux!=NULL)){ cout<<aux->dato<<&quot;n&quot;; 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
  • void menu(){ int opcion; while(opcion<4){ system(&quot;cls&quot;); cout<<&quot;1. Insertarn&quot;; cout<<&quot;2. Mostrarn&quot;; cout<<&quot;3. Contar Nodosn&quot;; cout<<&quot;4. Salirn&quot;; cout<<&quot;Seleccione: &quot;; cin>>opcion; switch(opcion){ case 1:{insertar(); break;} case 2: { mostrar_circular(); break;} case 3: { cout<<&quot;La lista tiene: &quot;<<contar_nodos()<<&quot; nodosn&quot;; break;} } } } void main(){ menu(); }
  • 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)
  • Pila #include <iostream.h> struct nodo{ int num; nodo *ant; }*inicio=NULL, *aux, *nuevo; void empilar(){ nuevo=new (nodo); cout<<&quot;Elemento: &quot;; cin>>nuevo->num; if(inicio==NULL){ nuevo->ant=NULL; inicio=nuevo; } else{ nuevo->ant=inicio; inicio=nuevo; } } void desempilar(){ aux=inicio; if(aux==NULL) cout<<&quot;Pila Vacian&quot;; else if(aux->ant==NULL) inicio=NULL; else inicio=inicio->ant; delete(aux); cout<<&quot;elemento borradon&quot;; } void mostrar(){ aux=inicio; if (aux==NULL) cout<<&quot;nLa pila esta vacian&quot;; while(aux!=NULL){ cout<<aux->num<<&quot;n&quot;; aux=aux->ant; } }
  • void main(){ int opcion; while(opcion<4){ cout<<&quot;1. Empilarn&quot;; cout<<&quot;2. Desempilarn&quot;; cout<<&quot;3. Mostrarn&quot;; cout<<&quot;4. Salirn&quot;; cout<<&quot;Seleccione una opcion: &quot;; cin>>opcion; switch(opcion){ case 1:{empilar(); break;} case 2:{desempilar(); break;} case 3:{mostrar(); break;} }//sw }//w }//v