Sei sulla pagina 1di 16

ESTRUCTURAS DE DATOS DINMICA

INTRODUCCIN
Todo programa que est siendo ejecutado por la CPU, ocupa un bloque de bytes en la memoria RAM del
computador. Cuando un computador inicia su funcionamiento, el programa que toma el control es el Sistema
Operativo. El mismo ocupa las direcciones bajas de memoria, es decir un bloque de bytes que comienza en la
posicin 0. Normalmente estas direcciones tienen un tamao de 4 bytes (32bits) y se representan en Hexadecimal.
De tal manera que la memoria RAM a la que se puede acceder en forma directa por la CPU comienza en la posicin
00 00 00 00 y termina en FF FF FF FF.
Cuando un programa se prepara para ejecutarse, el sistema operativo le asigna un bloque de memoria RAM
que se divide en los siguientes sectores: CDIGO, DATOS, STACK (PILA), HEAP (MONTN o MONTCULO).
El sector CDIGO contiene las instrucciones del programa en lenguaje de mquina absoluto, el de DATOS
contendr las variables globales del programa, en el STACK se almacenar las variables locales y los parmetros por
valor de las funciones que utilice el programa, tambin se guarda all la direccin del cdigo donde deber retornar
cuando termine su ejecucin y en el HEAP, que suele ser mucho ms grande que los otros sectores, se utilizar para
almacenar estructuras de datos que requieren cambiar su tamao durante la ejecucin del programa y necesitan
gran cantidad de bloques de bytes.
Una distribucin tpica de estos sectores se representa en el siguiente esquema:

MEMORIA RAM

En general los bloques de byte en el sector Stack,


se van asignando a medida que se ejecutan las
funciones y se liberan cuando las mismas
finalizan; funcionando como una verdadera pila
de datos, ya que el ltimo bloque que se ocupa es
el primero que se desocupa cuando la funcin
correspondiente termina su ejecucin. El Stack
crece desde una posicin determinada hacia la
parte baja de la memoria.
Por su parte, el Heap va creciendo desde una
posicin determinada, normalmente la que sigue
a la posicin de inicio del Stack, hacia la parte alta
de la memoria. Los bloques de byte se van
asignando mediante acciones del programa y su
manejo es muy particular, ya que se va ocupando
y desocupando bloques de memoria en forma
prcticamente aleatoria tratando de aprovechar
al mximo el espacio que va quedando liberado o
disponible.

Los tipos de datos que se almacenan en el sector DATOS y en el STACK, ocupan un espacio fijo de memoria
que no puede cambiarse durante la ejecucin del programa. Por ello es que se llama estos tipos Estructuras
ESTTICAS, por ejemplo las variables simples tipo entero, real, lgicas o carcter, los arreglos, las cadenas, los
registros.
Por otro lado, los datos que se almacenan en el HEAP tienen como caracterstica que el espacio de memoria
ocupado por los mismos puede aumentar o disminuir durante la ejecucin del programa. De ah el nombre de
Estructuras DINMICAS, por ejemplo las listas, pilas, colas, rboles y grafos.

TIPO PUNTERO
Un tipo puntero representa la direccin de memoria de un bloque de byte correspondiente a una estructura de
datos cualquiera. Las variables de tipo puntero ocupan 4 bytes de memoria, de tal manera que pueden contener
valores en el rango hexadecimal de 00 00 00 00 a FF FF FF FF. Estas variables se alojan en el Sector DATOS o
STACK, segn donde se declaren, en forma esttica; pero, como veremos a continuacin, nos permitirn acceder al
Sector HEAP para manejar Estructuras Dinmicas de Datos.
En lenguaje C++ se declaran las variables punteros utilizando la siguiente sintaxis:
<tipo apuntado> *<identificador puntero>
Por ejemplo:
Char *pun_caracter; // puntero a un tipo char o caracter
int *pun_entero;

// puntero a un tipo int o entero

float *pun_real;

// puntero a un tipo float o real

typedef char tipo_cadena [11]

// declaracin de identificador de tipo cadena de 10 caracteres como mximo

tipo_cadena *pun_cadena

// puntero a un tipo cadena

typedef int tipo_vec_entero[5]

// declaracin de identificador de tipo vector de 5 enteros como mximo

tipo_vec_entero *pun_vec_entero

// puntero a un tipo vector de enteros

struct tipo_registro { int campo1; tipo_cadena campo2; };


tipo_registro *pun_registro;

// declaracin de un identificador de tipo registro

// puntero a un tipo registro

Si queremos saber la posicin de memoria donde comienza el bloque de bytes de alguna variable del
programa, podemos utilizar el operador de direccin &. Este operador va seguido del identificador de la variable
en cuestin.
Por otro lado, si queremos acceder a un bloque de bytes cuya posicin se encuentra almacenada en una
variable puntero, utilizamos el operador de indireccin *. Este operador antecede al identificador de la variable
puntero y hara las veces de identificador del bloque de bytes en cuestin.
Por ejemplo, supongamos que se declara una variable tipo entero var_entero y un puntero a dicho tipo
pun_entero, luego se puede asignar a este puntero la direccin de la variable tipo entero. De tal modo que
desde pun_entero se podra manipular el valor de var_entero, de la siguiente manera:
int var_entero, *pun_entero; pun_entero = &var_entero; *pun_entero = 135;
printf(El valor de la variable <var_entero> es %d, var_entero); // esto mostrara por pantalla el valor 135
En el caso de un puntero a estructura registro, existen dos formas de referenciar un campo del registro mediante el
puntero: (*pun_registro).campo1 o pun_registro->campo1

ASIGNACIN DINMICA DE MEMORIA


En realidad, la posibilidad de direccionar variables estticas con punteros no tiene mucha utilidad. Lo que si
nos interesa es poder acceder al Sector HEAP de la memoria y poder crear estructuras dinmicas, para lo cual
vamos a utilizar las variables punteros.
Para poder asignar a un puntero la direccin de memoria de un bloque de bytes del Sector HEAP, el
lenguaje C dispone de la funcin estndar malloc() en la biblioteca <stdlib.h>, que lleva como argumento el tamao
del bloque y devuelve un puntero a void, de tal modo que con la conversin (casting) conveniente en general
(<tipo dato>*) - se puede convertir a un puntero del tipo del bloque, que contendr la direccin del primer byte de
dicho bloque de dato. En el caso del C++ se cuenta adems con el operador new, que lleva como operando el tipo
de dato correspondiente al bloque y devuelve como resultado un puntero al mismo. En ambos casos, si se produce
algn problema con la asignacin de memoria en el HEAP, por ejemplo falta de espacio, se devuelve el valor NULL.
Si bien con los dos mecanismos se termina reservando un bloque de bytes en el HEAP y se obtiene la posicin del
mismo, podemos afirmar que el operador new resulta ms eficiente.
Como dijimos, la caracterstica principal de la asignacin dinmica de memoria es la de poder variar el
tamao de memoria que ocupa la estructura de datos. Podemos observar que cada vez que se asigna un bloque de
byte, como vimos anteriormente, se aumenta el espacio ocupado. Pero es importante que cuando no necesitemos
ms esos bloques, podamos desocuparlos o liberarlos y de ese modo disminuir el espacio de memoria que ocupa la
estructura. Esto lo hacemos en el lenguaje C con la funcin free() de la biblioteca <stdlib.h>, que lleva como
argumento la variable puntero al bloque de byte que queremos liberar. En el lenguaje C++ tenemos el operador
delete que tambin lleva como operando al puntero. Por supuesto que cuando trabajamos con la funcin malloc()
debemos usar la funcin free() y cuando utilizamos el operador new debemos usar delete.
Por ejemplo, supongamos que deseamos almacenar en el HEAP un registro con los datos personales de un
empleado: Nombre, DNI, Salario; tendramos el siguiente cdigo en C++ :
#include <stdio.h>
#include <stdlib.h>
#include <conio.c>
typedef char tipo_nombre[20];
struct dato_personal {tipo_nombre nombre; long dni; float salario;};
main()
{ dato_personal *pun_dato;
pun_dato = new(dato_personal); // pun_dato = (dato_personal *) malloc(sizeof(dato_personal));
clrscr();
if (pun_dato!=NULL)
{ printf("Nombre = "); gets(pun_dato->nombre);
printf("DNI = "); scanf("%ld", &pun_dato->dni);
printf("Salario = "); scanf("%f", &pun_dato->salario);
printf("\n\nEl registro ingresado es: %s , %ld , %.2f", pun_dato->nombre, pun_dato->dni, pun_dato->salario);}
else {printf("Error fatal en el HEAP"); exit(1);}
getch();
}

Veamos el siguiente ejemplo donde se podr apreciar cmo se va asignando la memoria para variables estticas de
distintos mbitos del programa (STACK o DATA) y en forma dinmica con punteros (HEAP):
#include <stdio.h>
#include <stdlib.h>
#include <conio.c>
int var_global0;
int var_global1;

La salida de este programa nos muestra las


posiciones de memoria en Hexadecimal, que
van ocupando las distintas variables globales
en el sector DATA y locales en el sector
STACK. Tambin muestra las direcciones de
memoria que se asignan a una variable
puntero, correspondientes al sector HEAP.

int fun_entero1(int param1)


{int var_local1;
printf("Dir var local1 stack: %x\n",&var_local1);
printf("Dir parametro1 stack: %x\n",&param1);}
int fun_entero2(int param2)
{int var_local2;
fun_entero1(25);
printf("Dir var local2 stack: %x\n",&var_local2);
printf("Dir parametro2 stack: %x\n",&param2);}
main()
{int var_main0, var_main1, *pun_main;
clrscr():
fun_entero2(25);
printf("Dir var global0 data: %x\n",&var_global0);
printf("Dir var global1 data: %x\n",&var_global1);
printf("Dir var0 local main stack: %x\n",&var_main0);
printf("Dir var1 local main stack: %x\n",&var_main1);
fun_entero1(25);
printf("Dir var puntero local main stack: %x\n",&pun_main);
pun_main = (int *)malloc(sizeof (int));
printf("Dir var heap con malloc: %x\n",pun_main);
pun_main = new int;
printf("Dir var heap con new: %x\n",pun_main);
getch();
}

Como vemos los tres sectores de memoria


RAM se ubican en direcciones distintas. En el
cado de las variables globales, se va asignando
la memoria en forma esttica en el sector
DATA (bloque 40 en Hexa) a medida que se
declaran dichas variables, en forma similar las
variables locales en el sector STACK (bloque 28
en Hexa) y por ltimo para las variables
dinmicas referenciadas por la variable
puntero del programa, se asigna memoria en el
sector HEAP (bloque 6C en Hexa).

ESTRUCTURA AUTOREFERENCIADA
Se llama estructura autoreferenciada a un registro que tiene al menos dos campos, en uno de los cuales se
almacena una informacin determinada y en el otro un puntero a la misma estructura. Se dice que esta definicin
es recursiva, ya que para declarar el tipo correspondiente a este registro se debe declarar un puntero al propio tipo
que se est declarando. Por ejemplo:
typedef char tipo_nombre[20];
struct dato_personal {tipo_nombre nombre; long dni; float salario; dato_personal *pun_dato_personal;};

Como vemos dentro de la declaracin del tipo dato_personal, hacemos referencia al propio tipo dato_personal
para declarar el campo pun_dato_personal.
Con esta clase de registros se pueden implementar estructuras dinmicas ms complejas, como ser: listas
enlazadas simples, listas enlazadas dobles, pilas y colas.

LISTA ENLAZADA SIMPLE:


Una Lista Enlazada Simple, es una estructura de datos homognea formada por nodos que son estructuras
autoreferenciadas, de tal modo que un nodo contiene una informacin ms la direccin de memoria del siguiente
nodo representada con un puntero.
Este tipo de estructuras se almacena en su totalidad en el HEAP de la
memoria RAM. Para acceder al primer nodo necesitamos definir una variable del programa que contenga la
direccin del HEAP correspondiente a ese nodo. Por otro lado el ltimo nodo de la lista tendr como direccin del
siguiente nodo el valor NULL.
Esquemticamente tendramos:
Pun_nodo

Nodo 1

Nodo 2

Nodo 3

Con las flechas representamos una direccin del HEAP y con el smbolo de toma tierra o masa representamos el
valor NULL.
Utilizando el ejemplo de la estructura anterior, el siguiente programa crea una lista con dos nodos y luego elimina
el primero de ellos, por cuestiones nemotcnicas llamaremos al campo puntero siguiente:
#include <stdio.h>
#include <stdlib.h>
#include <conio.c>
typedef char tipo_nombre[20];
struct dato_personal {tipo_nombre nombre; long dni; float salario; dato_personal *siguiente;};
main()
{ dato_personal *pun_dato,*pun_aux;
pun_dato = new(dato_personal);
//pun_dato = (dato_personal *) malloc(sizeof(dato_personal));
clrscr();

if (pun_dato!=NULL)
{ printf("Introducir los datos de una persona:\n");
printf("Nombre = "); gets(pun_dato->nombre);
printf("DNI = "); scanf("%ld", &pun_dato->dni);
printf("Salario = "); scanf("%f", &pun_dato->salario);
pun_dato->siguiente = new(dato_personal);
printf("\n\nEl primer registro ingresado es: %s , %ld , %.2f\nesta en la direccion %x del HEAP, ocupa %d
bytes\ny apunta al segundo registro\n\n", pun_dato->nombre, pun_dato->dni, pun_dato->salario, pun_dato,
sizeof(dato_personal));
if (pun_dato->siguiente!=NULL)
{ printf("Introducir los datos de otra persona:\n");
printf("Nombre = "); fflush(stdin); gets(pun_dato->siguiente->nombre);
printf("DNI = "); scanf("%ld", &pun_dato->siguiente->dni);
printf("Salario = "); scanf("%f", &pun_dato->siguiente->salario);
pun_dato->siguiente->siguiente = NULL;
printf("\n\nEl segundo registro ingresado es: %s , %ld , %.2f\nesta en la direccion %x del HEAP\ny no
apunta a ningun otro registro\n\n", pun_dato->siguiente->nombre, pun_dato->siguiente->dni,
pun_dato->siguiente->salario, pun_dato->siguiente);
pun_aux=pun_dato;
pun_dato=pun_dato->siguiente;
delete(pun_aux);
// free(pun_aux);
printf("Eliminamos el primer registro,\nahora el primer registro esta en la direccion %x", pun_dato);
}
else {printf("Error fatal en el HEAP"); exit(1);}
}
else {printf("Error fatal en el HEAP"); exit(1);}
getch();
}
Una estructura como sta solo puede recorrerse en forma secuencial, es decir que para acceder al nodo I debemos
pasar por los (I-1) nodos anteriores, siempre comenzando por el primer nodo. Consideremos el caso de una lista a
la que se ingresan N nodos y supongamos que queremos acceder al nodo I para mostrar su contenido, podemos
utilizar una variable puntero auxiliar para recorrer los nodos de la lista, de la siguiente manera:
#include <stdio.h>
#include <stdlib.h>
#include <conio.c>
typedef char tipo_nombre[20];
struct dato_personal {tipo_nombre nombre; long dni; float salario; dato_personal *siguiente;};
main()
{ dato_personal *pun_dato,*pun_aux;
int j,N,I;
clrscr();
printf("Introducir la cantidad de personas: "); scanf("%d",&N);
if (N==0) { pun_dato=NULL; printf("Lista vacia"); getch();}

else
{ pun_dato = new(dato_personal);
pun_aux = pun_dato;
j=0;
do
{
if (pun_aux!=NULL)
{ printf("Introducir los datos de una persona:\n");
printf("Nombre = "); fflush(stdin); gets(pun_aux->nombre);
printf("DNI = "); scanf("%ld", &pun_aux->dni);
printf("Salario = "); scanf("%f", &pun_aux->salario);
}
else {printf("Error fatal en el HEAP"); exit(1);}
j++;
if (j==N) {pun_aux->siguiente = NULL; break;}
pun_aux->siguiente = new(dato_personal);
pun_aux=pun_aux->siguiente;
}
while (true);
clrscr();
pun_aux=pun_dato;
j=0;
while (pun_aux != NULL)
{printf("El nodo %d tiene el siguiente contenido: %s , %ld , %.2f\n\n",
j, pun_aux->nombre, pun_aux->dni, pun_aux->salario);
pun_aux=pun_aux->siguiente;
j++;
}
clrscr();
do
{
printf("Introduzca nmero de nodo a ver o '0' para terminar:"); scanf("%d",&I);
if (I==0) break;
pun_aux = pun_dato;
j = 1;
while ((pun_aux != NULL) && (j < I)) {pun_aux = pun_aux->siguiente; j++; }
if (pun_aux != NULL) printf("El nodo %d tiene el siguiente contenido: %s , %ld , %.2f\n\n",
j, pun_aux->nombre, pun_aux->dni, pun_aux->salario);
else printf("La lista tiene %d nodos.\n\n", j-1 );
}
while (true);
}
}

Otro ejemplo es el caso de una lista ordenada por algn campo clave, en nuestro caso podra ser el campo dni.
Para manejar una lista como sta, se definen las siguientes operaciones bsicas:
Crear lista vaca.
Insertar un nodo de tal modo que la lista quede ordenada por el campo clave.
Eliminar, modificar o mostrar un nodo con un campo clave determinado.
Listar todos los nodos.
El siguiente programa realiza estas tareas mediante un men y la utilizacin de funciones para cada operacin:
#include <stdio.h>
#include <stdlib.h>
#include <conio.c>
typedef char tipo_nombre[20];
struct dato_personal {tipo_nombre nombre; long dni; float salario; dato_personal *siguiente;};
typedef dato_personal *tipo_pun_dato;
void crear_lista_vacia(tipo_pun_dato &pun)
{pun=NULL;}

void insertar_nodo_ordenado(tipo_pun_dato &pun)


{tipo_pun_dato aux, act, ant;
aux=new(dato_personal);
act=pun;
ant=pun;
if (aux!=NULL)
{ printf("Introducir los datos de una persona:\n");
printf("DNI = "); scanf("%ld", &aux->dni);
while ((act!=NULL) && (act->dni < aux->dni)) {ant=act; act=act->siguiente;}
if (act!=ant)
{
if (act!=NULL)
if (act->dni != aux->dni)
{ printf("Nodo intermedio:\n");
printf("Nombre = "); fflush(stdin); gets(aux->nombre);
printf("Salario = "); scanf("%f", &aux->salario);
aux->siguiente=act;
ant->siguiente=aux;
}
else printf("\nYa existe un nodo con ese dni\n\n");
else {printf("Ultimo nodo:\n");
printf("Nombre = "); fflush(stdin); gets(aux->nombre);
printf("Salario = "); scanf("%f", &aux->salario);

aux->siguiente=NULL;
ant->siguiente=aux;
}
}
else {printf("Primer nodo:\n");
printf("Nombre = "); fflush(stdin); gets(aux->nombre);
printf("Salario = "); scanf("%f", &aux->salario);
aux->siguiente=pun;
pun=aux;
}
}
else printf("Error fatal en el HEAP no se puede insertar un nodo");
}
void eliminar_nodo(tipo_pun_dato &pun)
{if (pun!=NULL)
{
long dni;
tipo_pun_dato act, ant;
act=pun;
ant=pun;
printf("Introducir el DNI de la persona a eliminar:\n");
printf("DNI = "); scanf("%ld", &dni);
while ((act!=NULL) && (act->dni < dni)) {ant=act; act=act->siguiente;}
if ((act!=NULL) && (act->dni == dni))
{if (ant!=act)
ant->siguiente=act->siguiente;
else pun=act->siguiente;
delete(act);
printf("\nNodo eliminado\n");
}
else printf("\nNo existe un nodo con ese dni\n\n");
}
else printf("LISTA VACIA");
}

void modificar_nodo(tipo_pun_dato &pun)


{if (pun!=NULL)
{
long dni;
tipo_pun_dato act;
act=pun;
printf("Introducir el DNI de la persona a eliminar:\n");
printf("DNI = "); scanf("%ld", &dni);

while ((act!=NULL) && (act->dni < dni)) act=act->siguiente;


if ((act!=NULL) && (act->dni == dni))
{ printf("Nombre = "); fflush(stdin); gets(act->nombre);
printf("Salario = "); scanf("%f", &act->salario);
printf("\nNodo modificado:\n");
}
else printf("\nNo existe un nodo con ese dni\n\n");
}
else printf("LISTA VACIA");
}
void mostrar_nodo(tipo_pun_dato &pun)
{if (pun!=NULL)
{
long dni;
tipo_pun_dato act, ant;
act=pun;
printf("Introducir el DNI de la persona a eliminar:\n");
printf("DNI = "); scanf("%ld", &dni);
while ((act!=NULL) && (act->dni < dni)) act=act->siguiente;
if ((act!=NULL) && (act->dni == dni))
{ printf("Nombre = %s\n",act->nombre);
printf("Salario = %.2f\n",act->salario);
}
else printf("\nNo existe un nodo con ese dni\n\n");
}
else printf("LISTA VACIA");
}
void listar_nodos(tipo_pun_dato &pun)
{
tipo_pun_dato act;
int j;
act=pun;
j=0;
if (pun==NULL) printf("LISTA VACIA");
else
{printf("| NODO | DNI |
NOMBRE
| SALARIO |\n");
while (act != NULL)
{printf("|%6d | %10ld | %-20s | %14.2f |\n",j+1, act->dni, act->nombre, act->salario);
act=act->siguiente;
j++;
}}
}

main()
{ tipo_pun_dato pun_dato;
int op;
crear_lista_vacia(pun_dato);
do
{
clrscr();
printf("
MENU\n");
printf("------------------------\n");
printf(" 1: INSERTAR\n");
printf(" 2: ELIMINAR\n");
printf(" 3: MODIFICAR\n");
printf(" 4: MOSTRAR\n");
printf(" 5: LISTAR\n");
printf(" 6: SALIR\n\n");
do
{ printf(" INTRODUCIR OPCION: ");
scanf("%d",&op);
if ((op>=1) && (op<=6)) break;
printf("Opcion no valida\n");
} while (true);
if (op==6) break;
clrscr();
switch (op)
{
case 1: insertar_nodo_ordenado(pun_dato); break;
case 2: eliminar_nodo(pun_dato); break;
case 3: modificar_nodo(pun_dato); break;
case 4: mostrar_nodo(pun_dato); break;
case 5: listar_nodos(pun_dato); break;
}
printf("\n\nPresione una tecla para continuar");
getch();
} while (true);
}

Por ltimo consideremos la posibilidad de guardar esta estructura en un archivo binario, de tal modo que quede
almacenada en forma permanente. Para ello definimos dos nuevas funciones, una para grabar la lista en un
archivo y otra para leer la lista desde ese archivo. Tambin se modific, por comodidad, la estructura del nodo.
De tal modo que contiene un campo registro que contiene la informacin propiamente dicha (nombre, dni, salario)
y otro campo para el puntero al siguiente nodo.

El siguiente programa resuelve este problema:


#include <stdio.h>
#include <stdlib.h>
#include <conio.c>
typedef char tipo_nombre[20];
struct tipo_registro {tipo_nombre nombre; long dni; float salario;};
struct dato_personal {tipo_registro registro; dato_personal *siguiente;};
typedef dato_personal *tipo_pun_dato;
void leer_lista_de_archivo(tipo_pun_dato &pun, tipo_nombre archi)
{FILE *m;
tipo_pun_dato aux,act;
tipo_registro r;
long tam=sizeof(tipo_registro);
pun=NULL;
m=fopen (archi, "rb");
if (m==NULL)
{printf ("\nArchivo inexistente o no se pudo abrir - se crea lista vacia");getch();}
else
{
fread(&r,tam,1,m);
if (feof(m)==0)
{aux=new(dato_personal);
if (aux!=NULL)
{aux->registro=r;
aux->siguiente=NULL;
pun=aux;}
else {printf ("\n Error en el HEAP - se interrumpe carga de la lista");getch();}
act=pun;
fread(&r,tam,1,m);
while (feof(m)==0)
{aux=new(dato_personal);
if (aux!=NULL)
{aux->registro=r;
aux->siguiente=NULL;
act->siguiente=aux;
act=aux;}
else {printf ("\n Error en el HEAP - se interrumpe carga de la lista");getch();}
fread(&r,tam,1,m);}
}
fclose(m);
}
}

void grabar_lista_en_archivo(tipo_pun_dato pun, tipo_nombre archi)


{FILE *m;
tipo_registro r;
long tam=sizeof(tipo_registro);
m=fopen(archi, "wb");
if (m==NULL)
{printf ("\n No se pudo crear el archivo - la lista no se grabo");getch();}
else
{
while (pun!=NULL)
{r=pun->registro;
fwrite(&r,tam,1,m);
pun=pun->siguiente;}
fclose(m);
}
}

void insertar_nodo_ordenado(tipo_pun_dato &pun)


{tipo_pun_dato aux, act, ant;
aux=new(dato_personal);
act=pun;
ant=pun;
if (aux!=NULL)
{ printf("Introducir los datos de una persona:\n");
printf("DNI = "); scanf("%ld", &aux->registro.dni);
while ((act!=NULL) && (act->registro.dni < aux->registro.dni)) {ant=act; act=act->siguiente;}
if (act!=ant)
{
if (act!=NULL)
if (act->registro.dni != aux->registro.dni)
{ printf("Nodo intermedio:\n");
printf("Nombre = "); fflush(stdin); gets(aux->registro.nombre);
printf("Salario = "); scanf("%f", &aux->registro.salario);
aux->siguiente=act;
ant->siguiente=aux;
}
else printf("\nYa existe un nodo con ese dni\n\n");
else {printf("Ultimo nodo:\n");
printf("Nombre = "); fflush(stdin); gets(aux->registro.nombre);
printf("Salario = "); scanf("%f", &aux->registro.salario);
aux->siguiente=NULL;

ant->siguiente=aux;
}
}
else {printf("Primer nodo:\n");
printf("Nombre = "); fflush(stdin); gets(aux->registro.nombre);
printf("Salario = "); scanf("%f", &aux->registro.salario);
aux->siguiente=pun;
pun=aux;
}
}
else printf("Error fatal en el HEAP no se puede insertar un nodo");
}
void eliminar_nodo(tipo_pun_dato &pun)
{if (pun!=NULL)
{
long dni;
tipo_pun_dato act, ant;
act=pun;
ant=pun;
printf("Introducir el DNI de la persona a eliminar:\n");
printf("DNI = "); scanf("%ld", &dni);
while ((act!=NULL) && (act->registro.dni < dni)) {ant=act; act=act->siguiente;}
if ((act!=NULL) && (act->registro.dni == dni))
{if (ant!=act)
ant->siguiente=act->siguiente;
else pun=act->siguiente;
delete(act);
printf("\nNodo eliminado\n");
}
else printf("\nNo existe un nodo con ese dni\n\n");
}
else printf("LISTA VACIA");
}

void modificar_nodo(tipo_pun_dato &pun)


{if (pun!=NULL)
{
long dni;
tipo_pun_dato act, ant;
act=pun;
printf("Introducir el DNI de la persona a eliminar:\n");
printf("DNI = "); scanf("%ld", &dni);
while ((act!=NULL) && (act->registro.dni < dni)) act=act->siguiente;

if ((act!=NULL) && (act->registro.dni == dni))


{ printf("Nombre = "); fflush(stdin); gets(act->registro.nombre);
printf("Salario = "); scanf("%f", &act->registro.salario);
printf("\nNodo modificado\n");
}
else printf("\nNo existe un nodo con ese dni\n\n");
}
else printf("LISTA VACIA");
}
void mostrar_nodo(tipo_pun_dato &pun)
{if (pun!=NULL)
{
long dni;
tipo_pun_dato act;
act=pun;
printf("Introducir el DNI de la persona a eliminar:\n");
printf("DNI = "); scanf("%ld", &dni);
while ((act!=NULL) && (act->registro.dni < dni)) act=act->siguiente;
if ((act->registro.dni == dni))
{ printf("Nombre = %s\n",act->registro.nombre);
printf("Salario = %.2f\n",act->registro.salario);
}
else printf("\nNo existe un nodo con ese dni\n\n");
}
else printf("LISTA VACIA");
}
void listar_nodos(tipo_pun_dato &pun)
{
tipo_pun_dato act;
int j;
act=pun;
j=0;
if (pun==NULL) printf("LISTA VACIA");
else
{printf("| NODO | DNI |
NOMBRE
| SALARIO |\n");
while (act != NULL)
{printf("|%6d | %10ld | %-20s | %14.2f |\n",j+1, act->registro.dni, act->registro.nombre, act>registro.salario);
act=act->siguiente;
j++;
}}
}

main()
{ tipo_pun_dato pun_dato;
int op;
tipo_nombre especifica_archi;
clrscr();
printf("Introducir la especificacion del archivo: ");
getch();
_flushall();gets(especifica_archi);
leer_lista_de_archivo(pun_dato,especifica_archi);
do
{
clrscr();
printf("
MENU\n");
printf("------------------------\n");
printf(" 1: INSERTAR\n");
printf(" 2: ELIMINAR\n");
printf(" 3: MODIFICAR\n");
printf(" 4: MOSTRAR\n");
printf(" 5: LISTAR\n");
printf(" 6: SALIR\n\n");
do
{ printf(" INTRODUCIR OPCION: ");
scanf("%d",&op);
if ((op>=1) && (op<=6)) break;
printf("Opcion no valida\n");
} while (true);
if (op==6) break;
clrscr();
switch (op)
{
case 1: insertar_nodo_ordenado(pun_dato); break;
case 2: eliminar_nodo(pun_dato); break;
case 3: modificar_nodo(pun_dato); break;
case 4: mostrar_nodo(pun_dato); break;
case 5: listar_nodos(pun_dato); break;
}
printf("\n\nPresione una tecla para continuar");
getch();
} while (true);
grabar_lista_en_archivo(pun_dato,especifica_archi);
}

Potrebbero piacerti anche