Sei sulla pagina 1di 29

Algoritmos y Programación II

Tipos de Datos de Secuencia

Escuela de Ingeniería Informática - Guayana


Prof. José Saad Khalil
Estructuras Autoreferenciadas

En ocasiones se trabaja con estructuras que tiene referencia a si misma, como lo


vimos en manejo de lista ,

typedef struct node {


char name[20];
int value;
struct node *next;
} Node;

Esta declaración recursiva de node podría parecer riesgosa, pero es correcta. Es


ilegal que una estructura contenga una instancia de si misma , pero

Declara a next, como un apuntador a node, no como un node en si, a veces se


puede tener estructuras que se hagan referencia una a la otra.
Listas

Las listas son una estructura de datos fundamental, empleadas para almacenar una
colección de elementos. Su importancia radical reside en que puede utilizarse para
implementar una amplia variedad de otros tipos de datos. Es decir TAD Lista sirve como
bases para implementar otros TAD más complicados.

Las listas constituyen una estructura flexible, ya que puede crecer y acortarse según se
requiera, los elementos son accesibles y se pueden insertar y suprimir en cualquier
posición de la lista. También se puede operar sobre listas, por ejemplo concatenarlas,
dividirlas en sub-listas o mezclarlas.
Listas
Una lista es una secuencia de ceros o más elementos de un determinado tipo y se
definir como una n-tupla dinámica (donde dinámica significa que los elementos
pueden cambiar con el tiempo) de la siguiente forma:

L=(a1, a2, … , an)

Donde n ≥ 0, n es la longitud de la lista o |L|. Si n=0 se dice que la lista es vacía y


para n≥1, a1 es el primer elemento o cabeza, an es el último elemento o cola y en

general ai está en la posición i.

No se impone ninguna restricción en los elementos de una lista, si todos los elementos
son de un mismo tipo (p.e. enteros) se dice que es homogénea. Sin embargo diferentes
tipos (p.e. enteros, flotantes, complejos) pueden ser almacenados en la lista entonces
se dice que la lista es heterogénea. En algunas aplicaciones se trabaja con lista de
listas:

L=((3),(4,5,6),(12,8,(10,11),2,()))
Estructuras para el manejo de Listas

#define MAX_ELEMENTOS 15

typedef struct{
int longitud;
int actual;
int elementos[MAX_ELEMENTOS];
} Lista;

typedef struct nodo{ lista ini fin


int elemento;
struct nodo *prox;
} nodo_t;

typedef struct{
nodo_t *ini,*fin;

} lista_t;
prox prox prox
Estructuras para el manejo de Listas

typedef struct nodo{


int elemento;
struct nodo *sig,*ant;
} nodo_t;

typedef struct{
nodo_t *ini,*fin; lista
} lista_t;
ini fin

ant sig ant sig ant sig


Estructuras para el manejo de Listas

typedef struct nodo{


int elemento;
struct nodo *sig,*ant;
} nodo_t;

typedef struct{
nodo_t *ini,*fin; lista
} lista_t;
ini fin

ant sig ant sig ant sig


Listas Delta
Algunas aplicaciones requieren llevar un control de tiempo asociado a elementos, por
ejemplo el tiempo de poner a dormir un proceso o el tiempo máximo de espera por un
evento. Cuando la cantidad de elementos crece, se puede llegar a necesitar una manera
de mantener un seguimiento eficaz de estos tiempos.

Si los elementos se almacenan simplemente en una lista ordenada, los elementos


tendrían que ser visitados en cada actualización del tiempo. Lo que en ciertos casos por
cuestión de rendimiento puede ser inaceptable, por ejemplo en la gestión de procesos
de un sistema de operación, siendo una lista delta una opción en esta situación.

En estas listas los elementos están ordenados de modo que su clave es la relativa a la
clave de los elementos que le precede. Por ejemplo, digamos que se tienen los
siguientes elementos, a, b, c, d, con retrasos de 10, 15, 12 y 22 unidades de tiempo de
espera respectivamente. Se pueden representar en una cola de prioridad (con clave los
tiempo de espera) de la siguiente formas: a, c, b, d, con claves de 10, 2, 3 y 7,
respectivamente.
TAD Pila

Una pila es un tipo especial de lista donde


todas las inserciones y supresiones tienen lugar
por un extremo denominado tope, una pila es
una lista que se maneja bajo la política donde
lo último en entrar primero en salir,
denominado LIFO (Por su siglas en ingles).
Una situación intuitiva de pila son por ejemplo
una pila de platos o una pila de libros,
situaciones donde puede ser conveniente
agregar o quitar elementos por la parte
superior o tope de la pila.
TAD Pila
El TAD pila incluye por lo general, cinco operaciones. Donde S es una pila y x es un
elemento.

Anula(S), convierta a S en una pila vacía.

Top(S), devuelve el valor del elemento que está en el tope de la pila.

Pop(S), suprime el primer elemento de la pila S, puede ser conveniente que retorne
el primer elemento.

Push(S,x), Mete o inserta el elemento x en la pila S.

Vacía(S), es cierto si S está vacía, en caso contrario falso.


TAD Pila (Implementación con Listas)

typedef struct nodo{


int elemento; stack top
struct nodo *next;
} nodo_t;

typedef struct{
nodo_t *top;
} stack; …
prox prox prox
stack * newStack()
{
stack *s;
if((s = (stack *)malloc(sizeof(stack))) == NULL)
exit(1);
s->top = NULL;
return s;
};
TAD Pila (Implementación con Listas)

void Anula(stack *s){


nodo_t *curp;
if(!s)
return;
for(curp = s->top ; curp ; curp = s->top){
s->top = curp->next;
free(curp);
}
}

int top(stack *s, int *value){ int vacia(stack *s){


if(s && s->top){ if(!s || !s->top)
*value = s->top->elemento; return 1;
return 1; return 0;
} }
return 0;
}
TAD Pila (Implementación con Listas)

int pop(stack *s, int *value){


if(s && s->top){
nodo_t * aux = s->top;
s->top = aux->next;
*value = aux->elemento;
free(aux);
return 1;
}
return 0;
}

int push(stack *s, int value){


nodo_t *newp;
if(!s) return 0;
if((newp = (nodo_t *)malloc(sizeof(nodo_t))) == NULL) exit(1);

newp->next = s->top;
newp->elemento = value;
s->top = newp;
return 1;
}
TAD Pila (Implementación con Listas)

int main(){
stack *s = newStack();
int x;
printf("Vacio: %d\n", vacia(s));
push(s,1);
push(s,2);
push(s,3);
push(s,4);

top(s, &x);
printf("Element At Top: %d\n", x);
pop(s, &x);
printf("Element Removed: %d\n", x);
top(s, &x);
printf("Element At Top: %d\n", x);
Anula(s);
printf("Vacio: %d\n", vacia(s));

return 0;
}
TAD Pila (Implementación con Arreglos)

Dada la naturaleza de las pilas, donde las


inserciones y supresiones ocurren por un
extremo o tope, la mejor manera de
implementarlas con arreglos es anclando la
base de pila al inicio del arreglo y dejar que
crezca hacia el otro extremo, un índice Tope
llamado tope (stack pointer) indicará la
posición actual del primer elemento de la
pila.
TAD Pila (Implementación con Arreglos)

int push(pila_t *pilap,int dato){


if(pilap->tope==MAX_PILA-1)
return 0;
#define MAX_PILA 10 pilap->elem[++pilap->tope]=dato;
return 1;
typedef struct{ }
int elem[MAX_PILA];
int tope;
}pila_t;
int top(pila_t *pilap,int *dato){
if(pilap->tope==-1)
return 0;
*dato=pilap->elem[pilap->tope];
return 1;
}
TAD Pila (Implementación con Arreglos)

int pop(pila_t *pilap,int *dato){


if(pilap->tope==-1)
return 0;
*dato=pilap->elem[pilap->tope--];
return 1;
}

int vacia(pila_t *pilap){


return pilap->tope==-1;
}

void anula(pila_t *pilap){


pilap->tope=-1;
}
TAD Pila (Implementación con Arreglos)
pila_t S;
int e;

printf("Implementacion de Pila\n");
anula(&S);
push(&S,1);
push(&S,2);
push(&S,3);
push(&S,4);
push(&S,5);
top(&S,&e);
printf("El elemento del tope es %d\n",e);
while(pop(&S,&e))
printf("%d\n",e);

Implementacion de Pila
El elemento del tope es 5
5
4
3
2
1
TAD Cola

Una cola son otro tipo especial de lista, en


el cual los elementos se insertan por un
extremo (el posterior) y se suprimen en el
otro (el anterior o frente), es decir se
maneja bajo la política donde lo primero
en entrar primero en salir, denominado
FIFO (Por su siglas en ingles).

Las colas son algo muy común en la vida


diaria y un TAD ampliamente utilizado en
aplicaciones de simulación, en el
planificador del sistema operativo, manejo
de entrada/salida, comunicaciones etc.
TAD Cola

Las operaciones ofrecidas por el TAD Lista pueden ser utilizadas para implementar el TAD
cola. A continuación se muestran operaciones sobre colas, donde Q es una cola y x un
elementos.

Anula(Q), convierte Q en una la cola vacía.

Frente(Q), Retorna el primer elemento de Q, e decir el que lleva más tiempo en Q.

Poner_en_cola(Q,x), Añade o Inserta en una cola Q el elemento x.

Quitar_de_cola(Q), Suprime el primer elemento de Q.

Vacía (Q), es cierta si Q está vacía, en caso contrario falso.


TAD Cola (Implementación con Listas)

queue
typedef struct nodo{
int elemento; ini fin
struct nodo *next;
} nodo_t;

typedef struct{
nodo_t *ini;
nodo_t *fin; …
} queue; ant sig ant sig ant sig

queue * newQueue()
{
queue *q;
if((q = (queue *)malloc(sizeof(queue))) == NULL)
exit(1);
q->ini = q->fin = NULL;
return q;
};
TAD Cola (Implementación con Listas)

void Anula(queue *q){


nodo_t *curp;
if(!q)
return;
for(curp = q->ini ; curp ; curp = q->ini){
q->ini = curp->next;
free(curp);
}
q->fin = NULL;
}

int frente(queue *q, int *value){


if(q && q->ini){
*value = q->ini->elemento;
return 1;
}
return 0;
}
TAD Cola (Implementación con Listas)

int quitar_de_cola(queue *q, int *value){


if(q && q->ini){
nodo_t * aux = q->ini;
q->ini = aux->next;
if(q->fin == aux)
q->fin = NULL;
*value = aux->elemento;
free(aux);
return 1;
}
return 0;
}

int vacia(queue *q){


if(!q || !q->ini)
return 1;
return 0;
}
TAD Cola (Implementación con Listas)

int poner_en_cola(queue *q, int value){


nodo_t *newp;
if(!q)
return 0;
if((newp = (nodo_t *)malloc(sizeof(nodo_t))) == NULL)
exit(1);

newp->next = NULL;
newp->elemento = value;

if(!q->ini){
q->ini = q->fin = newp;
}else{
q->fin->next = newp;
q->fin = newp;
}
return 1;
}
TAD Cola (Implementación con Listas)

int main(){
queue *q = newQueue();
int x;
printf("Vacio: %d\n", vacia(q));
poner_en_cola(q,1);
poner_en_cola(q,2);
poner_en_cola(q,3);
poner_en_cola(q,4);

frente(q, &x);
printf("Element in front: %d\n", x);
quitar_de_cola(q, &x);
printf("Element Removed: %d\n", x);
frente(q, &x);
printf("Element in front: %d\n", x);
Anula(q);
printf("Vacio: %d\n", vacia(q));

return 0;
}
TAD Cola (Arreglos Circulares)

La implementación de listas con arreglos mostrada Frente


anteriormente no es muy eficiente para la
implementación de colas ya que implica mover
todos los elementos durante la supresión lo que
implica un orden de n para esta operación. Para
evitar este coste se debe adoptar un enfoque
diferente, es imaginarse el arreglo como un círculo
donde primera posición sigue a la última y dos
índice que indican el frente y la cola, de esta forma
insertar y suprimir se realizan en un número
constantes de pasos.
Ultimo
TAD Cola (Arreglos Circulares)
#define MAX_COLA 10

typedef struct{
int elem[MAX_COLA];
int cuenta;
int frente;
int ultimo;
}cola_t;

void anula(cola_t *colap){


colap->cuenta=colap->frente=colap->ultimo=0;
}

int vacia(cola_t *colap){


return colap->cuenta==0;
}

int frente(cola_t *colap,int *dato){


if(colap->cuenta==0)
return 0;
*dato=colap->elem[colap->frente];
return 1;
}
TAD Cola (Arreglos Circulares)

int poner_en_cola(cola_t *colap,int dato){


if(colap->cuenta==MAX_COLA)
return 0;
colap->cuenta++;
colap->elem[colap->ultimo]=dato;
colap->ultimo=(colap->ultimo+1)%MAX_COLA;
return 1;
}

int quitar_de_cola(cola_t *colap,int *dato){


if(colap->cuenta==0)
return 0;
colap->cuenta--;
*dato=colap->elem[colap->frente];
colap->frente=(colap->frente+1)%MAX_COLA;
return 1;
}
TAD Cola (Arreglos Circulares)

cola_t Q;
int e;

printf("Implementacion de cola\n");
anula(&Q);
poner_en_cola(&Q,1);
poner_en_cola(&Q,2);
poner_en_cola(&Q,3);
poner_en_cola(&Q,4);
poner_en_cola(&Q,5); Implementacion de cola
frente(&Q,&e); Primer elemento:1
printf("Primer elemento:%d\n",e); 1
while(quitar_de_cola(&Q,&e)) 2
printf("%d\n",e); 3
4
5

Potrebbero piacerti anche