Está en la página 1de 7

Solución informática:

aplicación Ecoviaje

Sonia López leal

Estructura de datos
Solución informática: aplicación Ecoviaje

Indicaciones:

Retoma las experiencias de ap Desarrolla una función o clase verificaFuncionamiento que verifique el


correcto funcionamiento de todas las funciones y métodos programados anteriormente.
rendizaje y participaciones de los foros realizados en unidades pasadas.
Elabora en un documento de texto, una tabla con las funciones de orden de magnitud o(f(n)) conocidas
también como Big-O de cada método o función implementada con una explicación muy breve sobre la
eficiencia de los algoritmos utilizados.
Integra a ese mismo documento una reflexión sobre la importancia que tienen las estructuras de datos para
hacer un uso eficiente del espacio de almacenamiento en memoria, optimizar el tiempo de acceso a los
datos almacenados y lograr formas efectivas de inserción, eliminación, recuperación, ordenamiento y
búsqueda de datos.
Recupera el código programado a lo largo del curso, e intégralo en un solo documento agregando la
función verificaFuncionamiento junto con la explicación sobre cómo utilizarla para realizar la verificación de
cada función y/o método realizado
Rendimiento de algoritmos y notación Big-O
En Ciencias de la Computación, el término eficiencia algorítmica es usado para describir aquellas
propiedades de los algoritmos que están relacionadas con la cantidad de recursos utilizados por el
algoritmo.
En programación el rendimiento o la complejidad de un algoritmo se suele medir utilizando una
notación denominada Big-O, y también conocida como Notación Asintótica o Notación Landau.
La notación Big-O nos proporciona una manera de saber cómo se va a comportar un algoritmo en función de
los argumentos que le pasemos y la escala de los mismos.
Atendiendo a su complejidad, las notaciones Big-O más comunes para todo tipo de algoritmos y funciones
son las que se muestran en esta lista:
O(1): constante. La operación no depende del tamaño de los datos. Es el caso ideal, pero a la vez
probablemente el menos frecuente.
O(n): lineal. El tiempo de ejecución es directamente proporcional al tamaño de los datos. Crece en una
línea recta.
O(log n): logarítmica. por regla general se asocia con algoritmos que "trocean" el problema para
abordarlo, como por ejemplo una búsqueda binaria.
O(nlogn): en este caso se trata de funciones similares a las anteriores, pero que rompen el problema
en varios trozos por cada elemento, volviendo a recomponer información tras la ejecución de
cada "trozo". Por ejemplo, el algoritmo de búsqueda Quicksort.
O(n2): cuadrática. Es típico de algoritmos que necesitan realizar una iteración por todos los
elementos en cada uno de los elementos a procesar. Por ejemplo el algoritmo de ordenación de burbuja. Si
tuviese que hacer la iteración más de una vez serían de complejidad O(n3), O(n4), etc... pero se trata de
casos muy raros y poco optimizados.
O(2n): exponencial. Se trata de funciones que duplican su complejidad con cada elemento añadido al
procesamiento. Son algoritmos muy raros pues en condiciones normales no debería ser necesario hacer algo
así. Un ejemplo sería, por ejemplo, el cálculo recursivo de la serie de Fibonacci, que es muy poco eficiente
(se calcula llamándose a sí misma la función con los dos números anteriores: F(n)=F(n-1)+F(n-2).
O(n!); explosión combinatoria. Un algoritmo que siga esta complejidad es un algoritmo totalmente fallido.
Una explosión combinatoria se dispara de tal manera que cuando el conjunto crece un poco, lo normal es
que se considere computacionalmente inviable. Solo se suele dar en algoritmos que tratan de resolver algo
por la mera fuerza bruta. No deberías verlo nunca en un software "real".
A medida que aumenta la complejidad, el tiempo necesario para completar la tarea crece mucho,
pudiendo llegar a aumentar enormemente en algunos casos en cuanto hay más datos.
#include<iostream>
#include<string.h>
#define true 1
#define false 0
using namespace std;
typedef struct solicitudes
{
char origen[20];
char destino[20];
char id[20];}
Solicitud;
typedef struct
{
Solicitud S[1000]; 
int ultimo; }
Lista; 
void inicializa(Lista &l);
void insertar(Lista *l,Solicitud S);
void compartir(Lista &A,Lista &B,Lista *C,Solicitud S);
void imprimir(Lista l);
void anular(Lista &l);
int main()
{
Lista A,B,C;
Solicitud aux; 
int opc,retorno;
inicializa(A); 
inicializa(B); i
nicializa(C); 
do{
 cout<<"\n\t\tListas de Solicitudes"<<endl; 
cout<<"\n\t1 - Insertar en lista A"; 
cout<<"\n\t2 - Insertar en lista B"; 
cout<<"\n\t3 - Compartir listas"; 
cout<<"\n\t4 - Eliminar lista A";
cout<<"\n\t5 - Eliminar lista B"; 
cout<<"\n\t6 - Mostrar listas";
cout<<"\n\t0 - Salir del programa"; 
cout<<"\n\tSeleccione opcion: "; cin>>opc;
fflush(stdin); 
if(opc==1||opc==2||opc==3)
 { 
if(opc==3) { 
cout<<"Ingresa el Origen y destino que compartiran lista desolicitudes";} 
cout<<"\nIngresa Origen:"; 
cin>>aux.origen; 
cout<<"\nIngresa Destino:"; 
cin>>aux.destino; 
if(opc!=3) 

cout<<"\nIngresa ID:";
cin>>aux.id;
}Lelse{strcpy(aux.id,"NULL");
}}
switch(opc)
{
case 1: insertar(&A,aux); 
cout<<"\nLISTA A:"; 
imprimir(A); 
break; 
case 2: insertar(&B,aux);
6
cout<<"\nLISTA B:"; 
imprimir(B); 
break; 
case 3: inicializa(C); 
compartir(A,B,&C,aux); 
break; 
case 4: anular(A); 
break; case 5: anular(B); 
break;
 case 6: 
cout<<"\nLISTA A:";
 imprimir(A);
cout<<"\nLISTA B:";
imprimir(B);
cout<<"\nLISTA C:";
imprimir(C);
 break; 
default: if(opc==0)

cout<<"\n\t\tSaldra del programa. Adios!!\n\n"; 
return 0; 

Else

cout<<"\n\t\t** Opcion fuera de rango. Vuelva a intentarlo. **\n"<<endl; 
}
 break;
7
} }while(opc);
return 0;
}
void inicializa(Lista &l){ l.ultimo = -1;
}void insertar(Lista *l,Solicitud S){ 
int i; 
if(l->ultimo==-1) { l->ultimo = 0;
} strcpy(l->S[l->ultimo].destino,S.destino); 
strcpy(l->S[l->ultimo].origen,S.origen); 
strcpy(l->S[l->ultimo].id,S.id); 
l->ultimo++; c
out<<"\n\tSe inserto:"<<S.id<<endl;
}void imprimir(Lista l){ int i = 0; 
if(l.ultimo==-1) {
 cout<<"\n\tLista vacia."<<endl; return;}
8
while(i<l.ultimo){
 cout<<"\n"<<"ID:"<<l.S[i].id<<" O:"<<l.S[i].origen<<"D:"<<l.S[i].destino<<"\n"<<endl; 
i=i+1;
 }}void anular(Lista &l){ if(l.ultimo = -1){ 
cout<<"\n\tTodos los elementos han sido borrados."<<endl;
 } 
else{ 
cout<<"\n\tNo hay elementos en la lista."<<endl; 
}}void compartir(Lista &A,Lista &B,Lista *C,Solicitud S){
int i=0,j=0,turno=1,turnos,t=0;
turnos = A.ultimo + B.ultimo;
while(t<turnos){
if(turno == 1)//REVISAR LISTA
A{if(strcmp(A.S[i].origen,S.origen)==0&&strcmp(A.S[i].destino,S.destino)==0){insertar(C,A.S[i]);turno =
2;
9
}i++;
}
else //REVISAR LISTA B
{
if(strcmp(B.S[j].origen,S.origen)==0&&strcmp(B.S[j].destino,S.destino)==0)
{insertar(C,B.S[j]);
turno = 1;
} j++;
}t++;
If(i==A.ultimo&&j <B.ultimo)
{
Turno 2;
If(i==B.ultimo&&j<A.ultimo)
{
Turno 1;
}
}
Nodo: Un árbol binario es un conjunto de elementos cada uno de los cuales se denomina nodo. Un
árbol Binario puede tener cero nodos y este caso se dice que está vacío. Puede tener un sólo nodo,
y en este caso solamente existe la raíz del árbol o puede tener un número finito de nodos. Cada
nodo puede estar ramificado por la izquierda o por la derecha o puede no tener ninguna
ramificación.
Con relación al tipo de nodos que hacen parte de los árboles, se identifican algunos nodos:
Nodo hijo: cualquiera de los nodos apuntados por uno de los nodos del árbol. En la gráfica  de la
imagen 2,  se tiene , ‘D’ y ‘M’  son hijos de ‘A’.
Nodo padre: nodo que contiene un puntero al nodo actual. En el ejemplo, el nodo ‘A’ es padre de ‘D’
y ‘D’.
 Los árboles con los que trabajará tienen otra característica importante: cada nodo sólo puede ser
apuntado por otro nodo, es decir, cada nodo sólo tendrá un padre. Esto hace que estos árboles
estén fuertemente jerarquizados, y es lo que en realidad les da la apariencia de árboles.
 En cuanto a la posición dentro del árbol se tiene:
Nodo raíz: nodo que no tiene padre. Este es el nodo que usaremos para referirnos al árbol. En el
ejemplo anterior, es el nodo  ‘A’.
Nodo hoja: nodo que no tiene hijos.

También podría gustarte