Imaginemos Un Mundo Libre

25
http://c.conclase.net/curso/ index.php?cap=029 Imaginemos un mundo libre El blog de Ronny, dedicado a la libertad de acceso al conocimiento. Listas enlazadas – Clase Lista,Nodo en c++ con 15 comentarios Una lista es una estructura de datos que nos permite agrupar elementos de una manera organizada. Las listas al igual que los algoritmos son importantísimas en la computación y críticas en muchos programas informáticos. Las listas están compuestas por nodos, estos nodos tienen un dato o valor y un puntero a otro(s) nodo(s). Existen varios tipos de listas: Simplemente enlazada, doblemente enlazada, circular simplemente enlazada, circular doblemente enlazada. Vamos a revisar las listas enlazadas simples, por ser el punto de partida y fundamentales para poder entender las otras. Una lista enlazada tiene un conjunto de nodos, los cuales almacenan 2 tipos de información: El dato que contienen y un puntero al siguiente nodo en la lista. El último nodo de la lista tiene como siguiente nodo el valor NULL. Entonces las listas enlazadas simples solo pueden ser recorridas en una dirección, apuntando al nodo siguiente, mas no a un nodo anterior. Aquí una ejemplo de un lista enlazada simple. ver fuente

description

Imaginemos Un Mundo Libre

Transcript of Imaginemos Un Mundo Libre

Page 1: Imaginemos Un Mundo Libre

http://c.conclase.net/curso/index.php?cap=029

Imaginemos un mundo libreEl blog de Ronny, dedicado a la libertad de acceso al conocimiento.

Listas enlazadas – Clase Lista,Nodo en c++

con 15 comentarios

Una lista es una estructura de datos que nos permite agrupar elementos de una manera organizada. Las listas al igual que los algoritmos son importantísimas en la computación y críticas en muchos programas informáticos.

Las listas están compuestas por nodos, estos nodos tienen un dato o valor y un puntero a otro(s) nodo(s).

Existen varios tipos de listas: Simplemente enlazada, doblemente enlazada, circular simplemente enlazada, circular doblemente enlazada.

Vamos a revisar las listas enlazadas simples, por ser el punto de partida y fundamentales para poder entender las otras. 

Una lista enlazada tiene un conjunto de nodos, los cuales almacenan 2 tipos de información: El dato que contienen y un puntero al siguiente nodo en la lista. El último nodo de la lista tiene como siguiente nodo el valor NULL. Entonces las listas enlazadas simples solo pueden ser recorridas en una dirección, apuntando al nodo siguiente, mas no a un nodo anterior.

Aquí una ejemplo de un lista enlazada simple.

ver fuente

imprimir ?

01 En cristiano:

02 55-> 60-> 31-> 5-> 4-> 51-> 9-> 27-> 68-> 62-> NULL

03

04 Internamente:05 Nodo-> Dato: 55 Direcion: 0x3d2c00 Siguiente: 0x3d2c8006 Nodo-> Dato: 60 Direcion: 0x3d2c80 Siguiente: 0x3d2c9007 Nodo-> Dato: 31 Direcion: 0x3d2c90 Siguiente: 0x3d2ca008 Nodo-> Dato: 5  Direcion: 0x3d2ca0 Siguiente: 0x3d2cb009 Nodo-> Dato: 4  Direcion: 0x3d2cb0 Siguiente: 0x3d2cc0

Page 2: Imaginemos Un Mundo Libre

10 Nodo-> Dato: 51 Direcion: 0x3d2cc0 Siguiente: 0x3d3ab811 Nodo-> Dato: 9  Direcion: 0x3d3ab8 Siguiente: 0x3d3ac812 Nodo-> Dato: 27 Direcion: 0x3d3ac8 Siguiente: 0x3d3ad813 Nodo-> Dato: 68 Direcion: 0x3d3ad8 Siguiente: 0x3d3ae8

14 Nodo-> Dato: 62 Direcion: 0x3d3ae8 Siguiente: 0

Obviamente, internamente no existen las palabras nodo, dato,dirección y siguiente, es solo una representación.

Como una lista es una estructura de datos dinámica, el tamaño de la misma puede cambiar durante la ejecución del programa.

Como vimos en post anteriores, se puede generar memoria dinámicamente para un array, pero un array es una estructura estática pues su tamaño tiene un limite y así creáramos array dinámicos hay que redimensionar el tamaño si es necesario, lo cual ya implica un costo de volver a generar memoria dinámica.

Entonces podemos ver una ventaja de la listas sobre los arrays: No tener que redimensionar la estructura y poder agregar elemento tras elemento indefinidamente.

Cuando uno ya ha trabajado con arrays (vectores y matrices) y empieza a estudiar las listas, se da cuenta que una restricción de las listas es el acceso a los elementos. En un vector podíamos hacer algo como v[50] y nos estábamos refiriendo al índice 50 del vector v. A esto se le conoce como acceso aleatorio.

En el caso de las listas el acceso es secuencial, es decir, para acceder a un elemento del conjunto debemos de recorrer uno por uno los elementos hasta llegar al solicitado. Rápidamente se puede concluir que el tiempo de acceso a los elementos de un array es muchísimo más rápido que en una lista. Esta es una gran desventaja de las listas, por lo que buscar elementos por índice sería muy costoso. Esto no quiere decir que trabajar con arrays sea mejor que con listas. Las listas son muy flexibles y para muchos casos son imprescindibles.

Bueno, aquí va la primera práctica que hice sobre listas enlazadas. Implementación de una clase Lista, clase Nodo y los siguientes métodos:

Añadir un elemento al inicio. Añadir un elemento al final Añadir un elemento de manera ordenada Llenar la lista por teclado Llenar la lista aleatoriamente Imprimir la lista Buscar un elemento Eliminar un elemento por dato Eliminar un elemento por posicion o índice Eliminar toda la lista Invertir una lista Ordernar una lista Cargar una lista desde archivo

Page 3: Imaginemos Un Mundo Libre

Guardar la lista en un archivo Concatenar una lista a otra Intersección entre 2 listas

Podrán ver la variable *temp en casi todos los métodos , este es el puntero de tipo Nodo que me va a permitir moverme a través de la lista y que inicialmente es igual a la cabeza (head). Mientras exista algo en la lista, voy avanzado el puntero para que apunte al siguiente. Esto se consigue en casi todos los casos con un while.

While(temp)temp = temp->gte

Otra operación común en los métodos es preguntar si inicialmente la lista está vacía, es decir, si la cabeza no contiene algo o es igual a Null.

if(!head) o if(head==NULL)

Apliqué mis limitados conocimientos de templates para tener una lista genérica y así pueda funcionar con varios tipos de datos y de verdad funciona.

Ahí la definición e implementación de la clase, lista, clase nodo y el main para ver el funcionamiento. Cualquier crítica, sugerencia o comentarios son bienvenidos siempre.

Nodo.h

ver fuente

imprimir ?

01 #ifndef NODO_H02 #define NODO_H03 #include <iostream>

04

05 using namespace std;

06 template <class T>

07 class Nodo

08 {

09   public:

10     T dato;11     Nodo *sgte;

12     Nodo();

13     Nodo(T);14     ~Nodo();

15

16     void print();

Page 4: Imaginemos Un Mundo Libre

17     void eliminar();

18 };

19

20 #endif // NODO_H

Nodo.cpp

ver fuente

imprimir ?

01 #include "Nodo.h"

02

03 //constructor por defecto

04 template<typename T>

05 Nodo<T>::Nodo()

06 {

07   dato = NULL;08   sgte = NULL;

09 }

1011 //constructor por parametro

12 template<typename T>

13 Nodo<T>::Nodo(T dato_)

14 {

15   dato = dato_;

16   sgte = NULL;

17 }

18

19 //imprimir un nodo

20 template<typename T>21 void Nodo<T>::print()

22 {

23   //cout << "Nodo-> " << "Dato: " << dato << " Direcion: " << this << " Siguiente: " << sgte << endl;

24   cout << dato << "-> ";

25 }

26

Page 5: Imaginemos Un Mundo Libre

27 //eliminar todos los nodos

28 template<typename T>

29 void Nodo<T>::eliminar()

30 {

31   if(sgte)

32     sgte->eliminar();33   delete this;

34 }

35

36 template<typename T>37 Nodo<T>::~Nodo(){}

Lista.h

ver fuente

imprimir ?

01 #ifndef LISTA_H02 #define LISTA_H

03

04 #include <iostream>

05 #include "time.h"

06 #include <fstream>07 #include <string>08 #include "Nodo.h"09 #include "Nodo.cpp"

10

11 using namespace std;

12

13 template <class T>

14 class Lista

15 {

16   private:17     int dim,num_nodos;

18     T line;

19     string archivo;

20

Page 6: Imaginemos Un Mundo Libre

21   public:

22     T ele;23     Nodo<T> *head;

24     Lista();

25     ~Lista();

26

27     void llenar_teclado(int);

28     void llenar_aleatorio(int);

29     void print();

30     void add_end(T);31     void add_head(T);32     void add_sort(T);

33     void search(T);

34     void del_dato(T);35     void del_pos(int);

36     void del_all();

37

38     void invertir();

39     void sort();

40     void load(string);41     void save(string);

42

43     void concat(Lista);

44     void interseccion(Lista);45 };

46

47 #endif // LISTA_H

Lista.cpp

ver fuente

imprimir ?

001 #include "Lista.h"

002

003 using namespace std;

004

Page 7: Imaginemos Un Mundo Libre

005 //constructor por defecto

006 template<typename T>

007 Lista<T>::Lista()

008 {

009   num_nodos = 0;

010   head = NULL;

011 }

012013 //llenar la lista por teclado

014 template<typename T>

015 void Lista<T>::llenar_teclado(int dim)

016 {

017   for(int i=0;i<dim;i++){

018     cout << "Ingresa el elemento " << i + 1 << endl;

019     cin >> ele;

020     add_end(ele);021   }

022 }

023

024 //llenar la lista aleatoriamente para enteros

025 template<typename T>

026 void Lista<T>::llenar_aleatorio(int dim)

027 {

028   srand(time(NULL));

029   for(int i=0;i<dim;i++){

030     add_end(rand() % 100);031   }

032 }

033

034 //imprimir la lista

035 template<typename T>

036 void Lista<T>::print()

037 {

038   Nodo<T> *temp = head;

Page 8: Imaginemos Un Mundo Libre

039   if(!head){

040     cout << "La lista esta vacia " << endl;

041   } else{

042     while(temp){

043       temp->print();

044       if(!temp->sgte) cout << "NULL";045       temp = temp->sgte;

046     }

047   }

048   cout << endl << endl;

049 }

050

051 //insertar al final

052 template<typename T>053 void Lista<T>::add_end(T dato_)

054 {

055   Nodo<T> *temp = head;

056   Nodo<T> *nuevo = new Nodo<T> (dato_);

057

058   if(!head){059       head = nuevo;

060   } else{

061     while(temp->sgte !=NULL){

062       temp = temp->sgte;

063     }

064     temp->sgte = nuevo;

065   }

066   num_nodos++;

067 }

068069 //insertar al inicio

070 template<typename T>

071 void Lista<T>::add_head(T dato_)

072 {

Page 9: Imaginemos Un Mundo Libre

073   Nodo<T> *temp = head;

074   Nodo<T> *nuevo = new Nodo<T> (dato_);

075

076   if(!head){077     head = nuevo;

078   } else{

079     nuevo->sgte = head;

080     head = nuevo;

081     while(temp){

082       temp = temp->sgte;083     }

084   }

085   num_nodos++;

086 }

087

088 //insertar de manera ordenada

089 template<typename T>

090 void Lista<T>::add_sort(T dato_)

091 {

092   Nodo<T> *nuevo = new Nodo<T> (dato_);093   Nodo<T> *temp = head;

094

095   if(!head){

096     head = nuevo;

097   } else{

098     if(head->dato > dato_){099       nuevo->sgte = head;

100       head = nuevo;

101     } else{

102       while((temp->sgte != NULL) && (temp->sgte->dato < dato_)){103         temp = temp->sgte;

104       }

105       nuevo->sgte = temp->sgte;

106       temp->sgte = nuevo;

107     }

Page 10: Imaginemos Un Mundo Libre

108   }

109   num_nodos++;

110 }

111

112 //buscar el dato de un nodo

113 template<typename T>

114 void Lista<T>::search(T dato_)

115 {

116   Nodo<T> *temp = head;117   int cont = 1;

118   int cont2=0;

119   while(temp){

120     if(temp->dato == dato_){

121      cout << "El dato se encuentra en la posicion: " << cont << " (Para seres humanos)" << endl;

122       cont2++;

123     }

124     temp = temp->sgte;125     cont++;

126   }

127   if(cont2 == 0){

128     cout << "No existe el dato " << endl;

129   }

130   cout << endl << endl;

131 }

132133 //eliminar por dato del nodo

134 template<typename T>

135 void Lista<T>::del_dato(T dato_)

136 {

137   Nodo<T> *temp = head;

138   Nodo<T> *temp1 = head->sgte;

139

140   int cont=0;

Page 11: Imaginemos Un Mundo Libre

141

142   if(head->dato == dato_){143     head = temp->sgte;

144   } else {

145     while(temp1){

146       if(temp1->dato == dato_){

147         Nodo<T> *aux = temp1;

148         temp->sgte = temp1->sgte;149         delete aux;

150         cont++;

151         num_nodos--;

152       }

153       temp = temp->sgte;

154       temp1 = temp1->sgte;155     }

156   }

157   if(cont == 0){

158     cout << "No existe el dato " << endl;159   }

160 }

161

162 //eliminar por posicion del nodo

163 template<typename T>

164 void Lista<T>::del_pos(int pos)

165 {

166   Nodo<T> *temp = head;167   Nodo<T> *temp1 = temp->sgte;

168

169   if(pos < 1 || pos > num_nodos){

170     cout << "Fuera de rango " << endl;

171   } else if(pos==1){

172     head = temp->sgte;

173   } else{

174     for(int i=2;i<=pos;i++){

Page 12: Imaginemos Un Mundo Libre

175       if(i==pos){

176         Nodo<T> *aux = temp1;177         temp->sgte = temp1->sgte;

178         delete aux;

179         num_nodos--;

180       }

181       temp = temp->sgte;

182       temp1 = temp1->sgte;183     }

184   }

185 }

186187 //eliminar todos los nodos

188 template<typename T>

189 void Lista<T>::del_all()

190 {

191   head->eliminar();

192   head = 0;

193 }

194

195 //invertir la lista

196 template<typename T>197 void Lista<T>::invertir()

198 {

199   Nodo<T> *temp = head;200   Nodo<T> *prev = NULL;201   Nodo<T> *next = NULL;

202

203   while(temp){

204     next = temp->sgte;205     temp->sgte = prev;

206     prev = temp;

207     temp = next;

208   }

209   head = prev;

210 }

Page 13: Imaginemos Un Mundo Libre

211

212 //ordenar de manera ascendente

213 template<typename T>

214 void Lista<T>::sort()

215 {

216   T aux2;217   Nodo<T> *aux = head;218   Nodo<T> *temp = aux;

219

220   while(aux){

221     temp=aux;

222     while(temp->sgte){223       temp=temp->sgte;

224

225       if(aux->dato>temp->dato){

226         aux2=aux->dato;

227         aux->dato=temp->dato;

228         temp->dato=aux2;

229       }

230     }

231     aux=aux->sgte;

232   }

233 }

234235 //cargar una lista de un archivo

236 template<typename T>

237 void Lista<T>::load(string archivo)

238 {

239   ifstream in;

240   in.open(archivo.c_str());

241

242   if(!in.is_open()){

243     cout << "No se puede abrir el archivo: " << archivo << endl << endl;

244   } else{

245     while(in >> line){

Page 14: Imaginemos Un Mundo Libre

246       add_end(line);

247     }

248   }

249   in.close();

250 }

251

252 //guardar una lista en un archivo

253 template<typename T>

254 void Lista<T>::save(string archivo)

255 {

256   Nodo<T> *temp = head;

257   ofstream out;

258   out.open(archivo.c_str());

259

260   if(!out.is_open()){261     cout << "No se puede guardar el archivo " << endl;

262   } else{

263     while(temp){

264       out << temp->dato;

265       out << " ";

266       temp = temp->sgte;267     }

268   }

269   out.close();

270 }

271

272 //concatenar a otra lista

273 template<typename T>

274 void Lista<T>::concat(Lista Lista2)

275 {

276   Nodo<T> *temp2 = Lista2.head;

277

278   while(temp2){279     add_end(temp2->dato);

Page 15: Imaginemos Un Mundo Libre

280     temp2 = temp2->sgte;

281   }

282 }

283

284 //numeros que coinciden en 2 listas

285 template<typename T>

286 void Lista<T>::interseccion(Lista Lista2)

287 {

288   Nodo<T> *temp = head;289   Nodo<T> *temp2 = Lista2.head;//cabeza de la segunda lista

290   Lista lista_interseccion;//creo otra lista

291

292   int num_nodos2 = Lista2.num_nodos;//nodos de la segunda lista293   int num_inter=0;//numero de coincidencias

294

295   //creo 2 vectores dinamicos

296   T *v1 = new T[num_nodos];

297   T *v2 = new T[num_nodos2];

298

299   //lleno los vectores v1 y v2 con los datos de la lista original y segunda lista respectivamente

300   int i=0;

301   while(temp){

302     v1[i] = temp->dato;303     temp = temp->sgte;

304     i++;

305   }

306

307   int j=0;

308   while(temp2){309     v2[j] = temp2->dato;310     temp2 = temp2->sgte;311     j++;

312   }

313

314   //ordeno los vectores

Page 16: Imaginemos Un Mundo Libre

315   insert_sort(v1,num_nodos);

316   insert_sort(v2,num_nodos2);

317

318   int v1_i= 0;//indice del 1er vector (v1)319   int v2_i= 0;//indice del 2do vector (v2)

320

321   //mientras no haya terminado de recorrer ambas listas

322   while (v1_i < num_nodos && v2_i < num_nodos2) {

323     if(v1[v1_i] == v2[v2_i]){//cuando los datos de ambas sean iguales

324       lista_interseccion.add_end(v1[v1_i]);//utilizo mi metodo add_end para llenar la lista de intersecciones

325       v1_i++;326       v2_i++;

327       num_inter++;

328     } else if(v1[v1_i] < v2[v2_i]){329       v1_i++;

330     } else{

331       v2_i++;

332     }

333   }

334

335   //Solo si hay alguna interseccion imprimo la nueva lista creada

336   if(num_inter > 0) {

337     cout << "Existen " << num_inter << " intersecciones " << endl;

338     lista_interseccion.print();

339   } else {

340     cout << "No hay interseccion en ambas listas" << endl;341   }

342 }

343

344 //usado por el metodo interseccion

345 template<typename T>

346 void insert_sort(T a[],int tam)

347 {

348   T temp;

349   for(int i=0;i<tam;i++){

Page 17: Imaginemos Un Mundo Libre

350     for(int j=i-1;j >=0 && a[j+1] < a[j];j--){351       temp = a[j+1];352       a[j+1] = a[j];353       a[j] = temp;

354     }

355   }

356 }

357

358 template<typename T>359 Lista<T>::~Lista(){}

main.cpp

ver fuente

imprimir ?

01 #include <iostream>

02 #include "Lista.h"

03 #include "Lista.cpp" //por errores de linking de tipo "undefined reference to" (estudiando)

04

05 using namespace std;

06 int main()

07 {

08   Lista<int> l1;09   Lista<int> l2;

10

11   int dim,pos;

12   string archivo;

13

14   cout << "Ingresa la dimension de la lista " << endl;15   cin >>dim;

16

17   l1.llenar_aleatorio(dim);//llenar_teclado para otros tipos

18

19   cout << "Lista A al inicio " << endl;

20   l1.print();

Page 18: Imaginemos Un Mundo Libre

21

22   cout << "Agrega un elemento por la cabeza" << endl;

23   cin >>l1.ele;

24   l1.add_head(l1.ele);25   l1.print();

26

27   cout << "Lista invertida " << endl;

28   l1.invertir();

29   l1.print();

30

31   cout << "Lista ordenada " << endl;

32   l1.sort();

33   l1.print();

34

35   cout << "Agrega un elemento (Sera ordenado)" << endl;

36   cin >>l1.ele;

37   l1.add_sort(l1.ele);

38   l1.print();

39

40   cout << "Busca un elemento" << endl;

41   cin >>l1.ele;

42   l1.search(l1.ele);

43

44   cout << "Elimina un elemento por dato" << endl;

45   cin >>l1.ele;

46   l1.del_dato(l1.ele);47   l1.print();

48

49   cout << "Elimina un elemento por posicion" << endl;

50   cin >>pos;

51   l1.del_pos(pos);

52   l1.print();

53

54   cout << "Cargar una lista desde archivo - Ingresa el nombre" << endl;

55   cin >> archivo;//debe estar en el mismo directorio que este

Page 19: Imaginemos Un Mundo Libre

programa

56   l2.load(archivo);

57   cout << "Lista B" << endl;

58   l2.print();

59

60   cout << "Guardar la lista en un archivo - Ingresa el nombre" << endl;

61   cin >> archivo;//ingresa un nombre cualquiera *.*

62   l2.save(archivo);

63

64   cout << "Interseccion entre las listas A y B " << endl;65   l1.interseccion(l2);

66

67   cout << "Listas A y B concatenadas " << endl;

68   l1.concat(l2);

69   l1.print();

70

71   l1.del_all();

72   l1.print();

73

74   return 0;75 }

Un ejemplo de la salida del programa:

ver fuente

imprimir ?

01 Ingresa la dimension de la lista

02 10

03 Lista A al inicio

04 55-> 60-> 31-> 5-> 4-> 51-> 9-> 27-> 68-> 62-> NULL

05

06 Agrega un elemento por la cabeza

07 18

08 18-> 55-> 60-> 31-> 5-> 4-> 51-> 9-> 27-> 68-> 62-> NULL

Page 20: Imaginemos Un Mundo Libre

09

10 Lista invertida11 62-> 68-> 27-> 9-> 51-> 4-> 5-> 31-> 60-> 55-> 18-> NULL

12

13 Lista ordenada

14 4-> 5-> 9-> 18-> 27-> 31-> 51-> 55-> 60-> 62-> 68-> NULL

15

16 Agrega un elemento (Sera ordenado)

17 45

18 4-> 5-> 9-> 18-> 27-> 31-> 45-> 51-> 55-> 60-> 62-> 68-> NULL

19

20 Busca un elemento

21 51

22 El dato se encuentra en la posicion: 8 (Para seres humanos)

23

24 Elimina un elemento por dato

25 60

26 4-> 5-> 9-> 18-> 27-> 31-> 45-> 51-> 55-> 62-> 68-> NULL

27

28 Elimina un elemento por posicion:

29 11

30 4-> 5-> 9-> 18-> 27-> 31-> 45-> 51-> 55-> 62-> NULL

31

32 Cargar una lista desde archivo - Ingresa el nombre33 prueba.txt // mi archivito prueba.txt tenia estos datos

34 Lista B

35 8-> 59-> 23-> 15-> 94-> 63-> 9-> 17-> 62-> 33-> NULL

36

37 Guardar la lista en un archivo - Ingresa el nombre

38 otralista.txt // abre tu archivo y mira el contenido39 Interseccion entre las listas A y B

40 Existen 2 intersecciones

41 9-> 62-> NULL

42

Page 21: Imaginemos Un Mundo Libre

43 Listas A y B concatenadas

44 4-> 5-> 9-> 18-> 27-> 31-> 45-> 51-> 55-> 62-> 8-> 59-> 23-> 15-> 94-> 63-> 9->17-> 62-> 33-> NULL

45

46 La lista esta vacia.