Vous êtes sur la page 1sur 17

Imaginemos un mundo libre

El blog de Ronny, dedicado a la libertad de acceso al conocimiento.


Listas enlazadas Clase Lista,Nodo en c++
con 17 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 importantsimas en la
computacin y crticas en muchos programas informticos.
Las listas estn 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
informacin: 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 direccin, apuntando al nodo siguiente,
mas no a un nodo anterior.
Aqu una ejemplo de un lista enlazada simple.
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: 0x3d2c80
06 Nodo-> Dato: 60 Direcion: 0x3d2c80 Siguiente: 0x3d2c90
07 Nodo-> Dato: 31 Direcion: 0x3d2c90 Siguiente: 0x3d2ca0
08 Nodo-> Dato: 5 Direcion: 0x3d2ca0 Siguiente: 0x3d2cb0
09 Nodo-> Dato: 4 Direcion: 0x3d2cb0 Siguiente: 0x3d2cc0
10 Nodo-> Dato: 51 Direcion: 0x3d2cc0 Siguiente: 0x3d3ab8
11 Nodo-> Dato: 9 Direcion: 0x3d3ab8 Siguiente: 0x3d3ac8
12 Nodo-> Dato: 27 Direcion: 0x3d3ac8 Siguiente: 0x3d3ad8
13 Nodo-> Dato: 68 Direcion: 0x3d3ad8 Siguiente: 0x3d3ae8
14 Nodo-> Dato: 62 Direcion: 0x3d3ae8 Siguiente: 0
Obviamente, internamente no existen las palabras nodo, dato,direccin y siguiente, es
solo una representacin.
Como una lista es una estructura de datos dinmica, el tamao de la misma puede
cambiar durante la ejecucin del programa.
Como vimos en post anteriores, se puede generar memoria dinmicamente para un
array, pero un array es una estructura esttica pues su tamao tiene un limite y as
creramos array dinmicos hay que redimensionar el tamao si es necesario, lo cual ya
implica un costo de volver a generar memoria dinmica.
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 restriccin de las listas es el acceso a los elementos. En un
vector podamos hacer algo como v[50] y nos estbamos 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.
Rpidamente se puede concluir que el tiempo de acceso a los elementos de un array es
muchsimo ms rpido que en una lista. Esta es una gran desventaja de las listas, por
lo que buscar elementos por ndice sera 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 prctica que hice sobre listas enlazadas. Implementacin de
una clase Lista, clase Nodo y los siguientes mtodos:
Aadir un elemento al inicio.
Aadir un elemento al final
Aadir 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
Guardar la lista en un archivo
Concatenar una lista a otra
Interseccin entre 2 listas
Podrn ver la variable *temp en casi todos los mtodos , este es el puntero de tipo
Nodo que me va a permitir moverme a travs 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 operacin comn en los mtodos es preguntar si inicialmente la lista est vaca,
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 genrica y as
pueda funcionar con varios tipos de datos y de verdad funciona.
Ah la definicin e implementacin de la clase, lista, clase nodo y el main para ver el
funcionamiento. Cualquier crtica, sugerencia o comentarios son bienvenidos siempre.
Nodo.h
01 #ifndef NODO_H
02 #define NODO_H
03 #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();
17
void eliminar();
18 };
19
20 #endif // NODO_H
Nodo.cpp
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 }
10
11 //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

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
01 #ifndef LISTA_H
02 #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

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
001 #include "Lista.h"
002

003
using namespace std;
004
005 //constructor por defecto
006
template<typename T>
007 Lista<T>::Lista()
008 {
009 num_nodos = 0;
010 head = NULL;
011 }
012
013 //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;
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 }
068

069 //insertar al inicio
070
template<typename T>
071
void Lista<T>::add_head(T dato_)
072 {
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 }
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 }
132
133 //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;
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++){
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 }
186

187 //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 }
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 }
234
235 //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){
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);
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 lista
293
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
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++){
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
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();
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
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:
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
09

10 Lista invertida
11 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 nombre
33 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 contenido
39 Interseccion entre las listas A y B
40 Existen 2 intersecciones
41 9-> 62-> NULL
42

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.
Gracias por tu visita al blog. Puedes seguirme en Twitter haciendo click en el siguiente
enlace

Vous aimerez peut-être aussi