[c5c522c] | 1 | #include <stdlib.h> |
---|
| 2 | #include <stdio.h> |
---|
| 3 | #include "LL.h" |
---|
| 4 | |
---|
| 5 | #ifdef DEBUG |
---|
| 6 | #undef DEBUG |
---|
| 7 | #endif |
---|
| 8 | |
---|
| 9 | //TODO: Comment everything |
---|
| 10 | //TODO: Test everything? |
---|
| 11 | |
---|
| 12 | ////////////////////////////////////////////////////////////////////// |
---|
| 13 | // Creates a new list... |
---|
| 14 | LL * LL_new() |
---|
| 15 | { |
---|
| 16 | LL *list; |
---|
| 17 | |
---|
| 18 | list = malloc(sizeof(LL)); |
---|
| 19 | if(!list) return NULL; |
---|
| 20 | |
---|
| 21 | list->head.data=NULL; |
---|
| 22 | list->head.prev=NULL; |
---|
| 23 | list->head.next=&list->tail; |
---|
| 24 | list->tail.data=NULL; |
---|
| 25 | list->tail.prev=&list->head; |
---|
| 26 | list->tail.next=NULL; |
---|
| 27 | list->current = &list->head; |
---|
| 28 | |
---|
| 29 | return list; |
---|
| 30 | } |
---|
| 31 | |
---|
| 32 | ////////////////////////////////////////////////////////////////////// |
---|
| 33 | // TODO: test this function |
---|
| 34 | // Destroys the entire list |
---|
| 35 | // Warning! Does not free the list data! (only the list itself) |
---|
| 36 | int LL_Destroy(LL *list) |
---|
| 37 | { |
---|
| 38 | LL_node *node, *next; |
---|
| 39 | |
---|
| 40 | if(!list) return -1; |
---|
| 41 | |
---|
| 42 | node = &list->head; |
---|
| 43 | |
---|
| 44 | for(node = node->next; node && node->next; node = next) |
---|
| 45 | { |
---|
| 46 | // Avoid accessing "node" after it's freed.. :) |
---|
| 47 | next = node->next; |
---|
| 48 | if(LL_node_Destroy(node) < 0) return -1; |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | free(list); |
---|
| 52 | |
---|
| 53 | return 0; |
---|
| 54 | } |
---|
| 55 | |
---|
| 56 | ////////////////////////////////////////////////////////////////////// |
---|
| 57 | // TODO: test this function |
---|
| 58 | // Warning! This does not assert that the node data is free! |
---|
| 59 | int LL_node_Destroy(LL_node *node) |
---|
| 60 | { |
---|
| 61 | if(!node) return -1; |
---|
| 62 | |
---|
| 63 | if(LL_node_Unlink(node) < 0) return -1; |
---|
| 64 | |
---|
| 65 | free(node); |
---|
| 66 | |
---|
| 67 | return 0; |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | ////////////////////////////////////////////////////////////////////// |
---|
| 71 | int LL_node_Unlink(LL_node *node) |
---|
| 72 | { |
---|
| 73 | LL_node *next, *prev; |
---|
| 74 | |
---|
| 75 | if(!node) return -1; |
---|
| 76 | |
---|
| 77 | next = node->next; |
---|
| 78 | prev = node->prev; |
---|
| 79 | |
---|
| 80 | if(next) |
---|
| 81 | next->prev = prev; |
---|
| 82 | if(prev) |
---|
| 83 | prev->next = next; |
---|
| 84 | |
---|
| 85 | node->next = NULL; |
---|
| 86 | node->prev = NULL; |
---|
| 87 | |
---|
| 88 | return 0; |
---|
| 89 | } |
---|
| 90 | |
---|
| 91 | ////////////////////////////////////////////////////////////////////// |
---|
| 92 | // Frees the data in a list node, if not NULL... |
---|
| 93 | int LL_node_DestroyData(LL_node *node) |
---|
| 94 | { |
---|
| 95 | if(!node) return -1; |
---|
| 96 | |
---|
| 97 | if(node->data) free(node->data); |
---|
| 98 | else return -1; |
---|
| 99 | return 0; |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | |
---|
| 103 | ////////////////////////////////////////////////////////////////////// |
---|
| 104 | // Returns to the beginning of the list... |
---|
| 105 | int LL_Rewind(LL *list) |
---|
| 106 | { |
---|
| 107 | if(!list) return -1; |
---|
| 108 | /* |
---|
| 109 | printf("LL_Rewind: list=%8x\n", list); |
---|
| 110 | printf("LL_Rewind: list.head=%8x\n", &list->head); |
---|
| 111 | printf("LL_Rewind: list.tail=%8x\n", &list->tail); |
---|
| 112 | */ |
---|
| 113 | |
---|
| 114 | if(list->head.next != &list->tail) |
---|
| 115 | list->current = list->head.next; |
---|
| 116 | else |
---|
| 117 | list->current = &list->head; |
---|
| 118 | |
---|
| 119 | return 0; |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | ////////////////////////////////////////////////////////////////////// |
---|
| 123 | // Goes to the end of the list... |
---|
| 124 | int LL_End(LL *list) |
---|
| 125 | { |
---|
| 126 | if(!list) return -1; |
---|
| 127 | |
---|
| 128 | if(list->tail.prev != &list->head) |
---|
| 129 | list->current = list->tail.prev; |
---|
| 130 | else |
---|
| 131 | list->current = &list->tail; |
---|
| 132 | |
---|
| 133 | return 0; |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | ////////////////////////////////////////////////////////////////////// |
---|
| 137 | // Go to the next node |
---|
| 138 | int LL_Next(LL *list) |
---|
| 139 | { |
---|
| 140 | if(!list) return -1; |
---|
| 141 | if(!list->current) return -1; |
---|
| 142 | |
---|
| 143 | if(list->current->next != &list->tail) |
---|
| 144 | { |
---|
| 145 | list->current = list->current->next; |
---|
| 146 | return 0; |
---|
| 147 | } |
---|
| 148 | else |
---|
| 149 | { |
---|
| 150 | return -1; |
---|
| 151 | } |
---|
| 152 | } |
---|
| 153 | |
---|
| 154 | ////////////////////////////////////////////////////////////////////// |
---|
| 155 | // Go to the previous node |
---|
| 156 | int LL_Prev(LL *list) |
---|
| 157 | { |
---|
| 158 | if(!list) return -1; |
---|
| 159 | if(!list->current) return -1; |
---|
| 160 | |
---|
| 161 | if(list->current->prev != &list->head) |
---|
| 162 | { |
---|
| 163 | list->current = list->current->prev; |
---|
| 164 | return 0; |
---|
| 165 | } |
---|
| 166 | else |
---|
| 167 | { |
---|
| 168 | return -1; |
---|
| 169 | } |
---|
| 170 | } |
---|
| 171 | |
---|
| 172 | |
---|
| 173 | ////////////////////////////////////////////////////////////////////// |
---|
| 174 | // Data manipulation |
---|
| 175 | void * LL_Get(LL *list) |
---|
| 176 | { |
---|
| 177 | if(!list) return NULL; |
---|
| 178 | if(!list->current) return NULL; |
---|
| 179 | |
---|
| 180 | return list->current->data; |
---|
| 181 | } |
---|
| 182 | |
---|
| 183 | ////////////////////////////////////////////////////////////////////// |
---|
| 184 | int LL_Put(LL *list, void *data) |
---|
| 185 | { |
---|
| 186 | if(!list) return -1; |
---|
| 187 | if(!list->current) return -1; |
---|
| 188 | |
---|
| 189 | list->current->data = data; |
---|
| 190 | |
---|
| 191 | return 0; |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | |
---|
| 195 | ////////////////////////////////////////////////////////////////////// |
---|
| 196 | LL_node * LL_GetNode(LL *list) |
---|
| 197 | { |
---|
| 198 | if(!list) return NULL; |
---|
| 199 | |
---|
| 200 | return list->current; |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | ////////////////////////////////////////////////////////////////////// |
---|
| 204 | // Don't use this unless you know what you're doing. |
---|
| 205 | int LL_PutNode(LL *list, LL_node *node) |
---|
| 206 | { |
---|
| 207 | if(!list) return -1; |
---|
| 208 | if(!node) return -1; |
---|
| 209 | |
---|
| 210 | list->current = node; |
---|
| 211 | |
---|
| 212 | return 0; |
---|
| 213 | } |
---|
| 214 | |
---|
| 215 | |
---|
| 216 | ////////////////////////////////////////////////////////////////////// |
---|
| 217 | void * LL_GetFirst(LL *list) // gets data from first node |
---|
| 218 | { |
---|
| 219 | if(!list) return NULL; |
---|
| 220 | |
---|
| 221 | if(0> LL_Rewind(list)) return NULL; |
---|
| 222 | |
---|
| 223 | return LL_Get(list); |
---|
| 224 | } |
---|
| 225 | |
---|
| 226 | ////////////////////////////////////////////////////////////////////// |
---|
| 227 | // |
---|
| 228 | void * LL_GetNext (LL *list) // ... next node |
---|
| 229 | { |
---|
| 230 | if(!list) return NULL; |
---|
| 231 | |
---|
| 232 | if(0 > LL_Next(list)) return NULL; |
---|
| 233 | |
---|
| 234 | return LL_Get(list); |
---|
| 235 | } |
---|
| 236 | |
---|
| 237 | ////////////////////////////////////////////////////////////////////// |
---|
| 238 | void * LL_GetPrev (LL *list) // ... prev node |
---|
| 239 | { |
---|
| 240 | if(!list) return NULL; |
---|
| 241 | |
---|
| 242 | if(0 > LL_Prev(list)) return NULL; |
---|
| 243 | |
---|
| 244 | return LL_Get(list); |
---|
| 245 | } |
---|
| 246 | |
---|
| 247 | ////////////////////////////////////////////////////////////////////// |
---|
| 248 | void * LL_GetLast (LL *list) // ... last node |
---|
| 249 | { |
---|
| 250 | if(!list) return NULL; |
---|
| 251 | |
---|
| 252 | if(0 > LL_End(list)) return NULL; |
---|
| 253 | |
---|
| 254 | return LL_Get(list); |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | ////////////////////////////////////////////////////////////////////// |
---|
| 258 | int LL_AddNode(LL *list, void * add) // Adds node AFTER current one |
---|
| 259 | { |
---|
| 260 | LL_node *node; |
---|
| 261 | |
---|
| 262 | if(!list) return -1; |
---|
| 263 | //if(!add) return -1; // Nevermind.. NULL entries can be good... |
---|
| 264 | if(!list->current) return -1; |
---|
| 265 | |
---|
| 266 | //LL_dprint(list); |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | node = malloc(sizeof(LL_node)); |
---|
| 270 | if(!node) return -1; |
---|
| 271 | //printf("Allocated node\n"); |
---|
| 272 | |
---|
| 273 | /* printf("Current: prev: %8x\tnode: %8x\tnext: %8x\n", */ |
---|
| 274 | /* (int)list->current->prev, */ |
---|
| 275 | /* (int)list->current, */ |
---|
| 276 | /* (int)list->current->next); */ |
---|
| 277 | if(list->current == &list->tail) |
---|
| 278 | { |
---|
| 279 | list->current = list->current->prev; |
---|
| 280 | /* printf("Was at end of list...\n"); */ |
---|
| 281 | /* printf("Current: prev: %8x\tnode: %8x\tnext: %8x\n", */ |
---|
| 282 | /* (int)list->current->prev, */ |
---|
| 283 | /* (int)list->current, */ |
---|
| 284 | /* (int)list->current->next); */ |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | // printf("Setting node data\n"); |
---|
| 288 | node->next = list->current->next; |
---|
| 289 | node->prev = list->current; |
---|
| 290 | node->data = add; |
---|
| 291 | // printf("...done\n"); |
---|
| 292 | /* printf("NewNode: prev: %8x\tnode: %8x\tnext: %8x\n", */ |
---|
| 293 | /* (int)node->prev, */ |
---|
| 294 | /* (int)node, */ |
---|
| 295 | /* (int)node->next); */ |
---|
| 296 | |
---|
| 297 | // printf("Relinking...\n"); |
---|
| 298 | if(node->next) |
---|
| 299 | node->next->prev = node; |
---|
| 300 | // printf("...\n"); |
---|
| 301 | list->current->next = node; |
---|
| 302 | // printf("...done\n"); |
---|
| 303 | |
---|
| 304 | list->current = node; |
---|
| 305 | |
---|
| 306 | // printf("Added node\n"); |
---|
| 307 | // LL_dprint(list); |
---|
| 308 | |
---|
| 309 | return 0; |
---|
| 310 | } |
---|
| 311 | |
---|
| 312 | ////////////////////////////////////////////////////////////////////// |
---|
| 313 | int LL_InsertNode(LL *list, void * add)// Adds node BEFORE current one |
---|
| 314 | { |
---|
| 315 | LL_node *node; |
---|
| 316 | |
---|
| 317 | if(!list) return -1; |
---|
| 318 | if(!add) return -1; |
---|
| 319 | if(!list->current) return -1; |
---|
| 320 | |
---|
| 321 | node = malloc(sizeof(LL_node)); |
---|
| 322 | if(!node) return -1; |
---|
| 323 | |
---|
| 324 | if(list->current == &list->head) list->current = list->current->next; |
---|
| 325 | |
---|
| 326 | node->next = list->current; |
---|
| 327 | node->prev = list->current->prev; |
---|
| 328 | node->data = add; |
---|
| 329 | |
---|
| 330 | if(list->current->prev) |
---|
| 331 | list->current->prev->next = node; |
---|
| 332 | |
---|
| 333 | list->current->prev = node; |
---|
| 334 | |
---|
| 335 | list->current = node; |
---|
| 336 | |
---|
| 337 | return 0; |
---|
| 338 | } |
---|
| 339 | |
---|
| 340 | //////////////////////////////////////////////////////////////////////// |
---|
| 341 | // Removes a node from the link |
---|
| 342 | // ... and advances one node forward |
---|
| 343 | void * LL_DeleteNode(LL *list) |
---|
| 344 | { |
---|
| 345 | LL_node *next, *prev; |
---|
| 346 | void *data; |
---|
| 347 | |
---|
| 348 | if(!list) return NULL; |
---|
| 349 | if(!list->current) return NULL; |
---|
| 350 | if(list->current == &list->head) return NULL; |
---|
| 351 | if(list->current == &list->tail) return NULL; |
---|
| 352 | |
---|
| 353 | #ifdef DEBUG |
---|
| 354 | printf("LL_DeleteNode: Before...\n"); |
---|
| 355 | LL_dprint(list); |
---|
| 356 | #endif |
---|
| 357 | |
---|
| 358 | |
---|
| 359 | next = list->current->next; |
---|
| 360 | prev = list->current->prev; |
---|
| 361 | data = list->current->data; |
---|
| 362 | |
---|
| 363 | if(prev) |
---|
| 364 | prev->next = next; |
---|
| 365 | |
---|
| 366 | if(next) |
---|
| 367 | next->prev = prev; |
---|
| 368 | |
---|
| 369 | list->current->prev = NULL; |
---|
| 370 | list->current->next = NULL; |
---|
| 371 | // This should not free things; the user should do it explicitly. |
---|
| 372 | //if(list->current->data) free(list->current->data); |
---|
| 373 | list->current->data = NULL; |
---|
| 374 | |
---|
| 375 | free(list->current); |
---|
| 376 | |
---|
| 377 | list->current = next; |
---|
| 378 | |
---|
| 379 | #ifdef DEBUG |
---|
| 380 | printf("LL_DeleteNode: After...\n"); |
---|
| 381 | LL_dprint(list); |
---|
| 382 | #endif |
---|
| 383 | |
---|
| 384 | return data; |
---|
| 385 | } |
---|
| 386 | ////////////////////////////////////////////////////////////////////// |
---|
| 387 | // Removes a specific node... |
---|
| 388 | void * LL_Remove(LL *list, void * data) |
---|
| 389 | { |
---|
| 390 | void *find; |
---|
| 391 | |
---|
| 392 | if(!list) return NULL; |
---|
| 393 | |
---|
| 394 | LL_Rewind(list); |
---|
| 395 | do { |
---|
| 396 | find = LL_Get(list); |
---|
| 397 | if(find == data) return LL_DeleteNode(list); |
---|
| 398 | } while (LL_Next(list) == 0); |
---|
| 399 | |
---|
| 400 | return NULL; |
---|
| 401 | } |
---|
| 402 | |
---|
| 403 | |
---|
| 404 | ////////////////////////////////////////////////////////////////////// |
---|
| 405 | // Stack operations |
---|
| 406 | int LL_Push(LL *list, void *add) // Add node to end of list |
---|
| 407 | { |
---|
| 408 | if(!list) return -1; |
---|
| 409 | if(!add) return -1; |
---|
| 410 | |
---|
| 411 | // printf("Going to end of list...\n"); |
---|
| 412 | LL_End(list); |
---|
| 413 | |
---|
| 414 | // printf("Adding node...\n"); |
---|
| 415 | return LL_AddNode(list, add); |
---|
| 416 | } |
---|
| 417 | |
---|
| 418 | ////////////////////////////////////////////////////////////////////// |
---|
| 419 | void * LL_Pop(LL *list) // Remove node from end of list |
---|
| 420 | { |
---|
| 421 | if(!list) return NULL; |
---|
| 422 | |
---|
| 423 | if(0 > LL_End(list)) return NULL; |
---|
| 424 | |
---|
| 425 | return LL_DeleteNode(list); |
---|
| 426 | } |
---|
| 427 | |
---|
| 428 | ////////////////////////////////////////////////////////////////////// |
---|
| 429 | void * LL_Top(LL *list) // Peek at end node |
---|
| 430 | { |
---|
| 431 | return LL_GetLast(list); |
---|
| 432 | } |
---|
| 433 | |
---|
| 434 | ////////////////////////////////////////////////////////////////////// |
---|
| 435 | void * LL_Shift(LL *list) // Remove node from start of list |
---|
| 436 | { |
---|
| 437 | if(!list) return NULL; |
---|
| 438 | |
---|
| 439 | if(0 > LL_Rewind(list)) return NULL; |
---|
| 440 | |
---|
| 441 | return LL_DeleteNode(list); |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | ////////////////////////////////////////////////////////////////////// |
---|
| 445 | void * LL_Look(LL *list) // Peek at first node |
---|
| 446 | { |
---|
| 447 | return LL_GetFirst(list); |
---|
| 448 | } |
---|
| 449 | |
---|
| 450 | ////////////////////////////////////////////////////////////////////// |
---|
| 451 | int LL_Unshift(LL *list, void *add) // Add node to beginning of list |
---|
| 452 | { |
---|
| 453 | if(!list) return -1; |
---|
| 454 | if(!add) return -1; |
---|
| 455 | |
---|
| 456 | LL_Rewind(list); |
---|
| 457 | |
---|
| 458 | return LL_InsertNode(list, add); |
---|
| 459 | } |
---|
| 460 | |
---|
| 461 | ////////////////////////////////////////////////////////////////////// |
---|
| 462 | int LL_Roll(LL *list) // Make last node first |
---|
| 463 | { |
---|
| 464 | LL_node *node, *next; |
---|
| 465 | |
---|
| 466 | if(!list) return -1; |
---|
| 467 | //if(!list->current) return -1; |
---|
| 468 | |
---|
| 469 | if(0 > LL_End(list)) return -1; |
---|
| 470 | |
---|
| 471 | // Avoid rolling an empty list, or unlinking the head/tail... |
---|
| 472 | if(list->current == &list->head) list->current = list->current->next; |
---|
| 473 | if(list->current == &list->tail) list->current = list->current->prev; |
---|
| 474 | // List is empty |
---|
| 475 | if(list->current == &list->head) return 0; |
---|
| 476 | // List has one item |
---|
| 477 | if(list->current->prev == &list->head) return 0; |
---|
| 478 | |
---|
| 479 | node = list->current; |
---|
| 480 | |
---|
| 481 | LL_node_Unlink(node); |
---|
| 482 | |
---|
| 483 | if(0 > LL_Rewind(list)) return -1; |
---|
| 484 | |
---|
| 485 | next = list->head.next; |
---|
| 486 | |
---|
| 487 | list->head.next = node; |
---|
| 488 | next->prev = node; |
---|
| 489 | node->prev = &list->head; |
---|
| 490 | node->next = next; |
---|
| 491 | |
---|
| 492 | return 0; |
---|
| 493 | } |
---|
| 494 | |
---|
| 495 | ////////////////////////////////////////////////////////////////////// |
---|
| 496 | int LL_UnRoll(LL *list)// Roll the other way... |
---|
| 497 | { |
---|
| 498 | LL_node *node, *prev; |
---|
| 499 | |
---|
| 500 | if(!list) return -1; |
---|
| 501 | //if(!list->current) return -1; |
---|
| 502 | |
---|
| 503 | if(0 > LL_Rewind(list)) return -1; |
---|
| 504 | |
---|
| 505 | // Avoid rolling an empty list, or unlinking the head/tail... |
---|
| 506 | if(list->current == &list->tail) list->current = list->current->prev; |
---|
| 507 | if(list->current == &list->head) list->current = list->current->next; |
---|
| 508 | // List is empty |
---|
| 509 | if(list->current == &list->tail) return 0; |
---|
| 510 | // List has one item |
---|
| 511 | if(list->current->next == &list->tail) return 0; |
---|
| 512 | |
---|
| 513 | node = list->current; |
---|
| 514 | |
---|
| 515 | LL_node_Unlink(node); |
---|
| 516 | |
---|
| 517 | if(0 > LL_End(list)) return -1; |
---|
| 518 | |
---|
| 519 | prev = list->tail.prev; |
---|
| 520 | |
---|
| 521 | list->tail.prev = node; |
---|
| 522 | prev->next = node; |
---|
| 523 | node->next = &list->tail; |
---|
| 524 | node->prev = prev; |
---|
| 525 | |
---|
| 526 | return 0; |
---|
| 527 | } |
---|
| 528 | |
---|
| 529 | |
---|
| 530 | |
---|
| 531 | ////////////////////////////////////////////////////////////////////// |
---|
| 532 | // Add an item to the end of its "priority group" |
---|
| 533 | // The list is assumed to be sorted already... |
---|
| 534 | int LL_PriorityEnqueue(LL *list, void *add, int compare(void *, void *)) |
---|
| 535 | { |
---|
| 536 | void *data; |
---|
| 537 | int i; |
---|
| 538 | |
---|
| 539 | if(!list) return -1; |
---|
| 540 | if(!add) return -1; |
---|
| 541 | if(!compare) return -1; |
---|
| 542 | |
---|
| 543 | // From the end of the list, keep searching while we're "less than" |
---|
| 544 | // the given nodes... |
---|
| 545 | LL_End(list); |
---|
| 546 | do { |
---|
| 547 | data = LL_Get(list); |
---|
| 548 | if(data) |
---|
| 549 | { |
---|
| 550 | i = compare(add, data); |
---|
| 551 | if(i >= 0) // If we're in the right place, add it and exit |
---|
| 552 | { |
---|
| 553 | LL_AddNode(list, add); |
---|
| 554 | return 0; |
---|
| 555 | } |
---|
| 556 | } |
---|
| 557 | } while(LL_Prev(list) == 0); |
---|
| 558 | |
---|
| 559 | // If we're less than *everything*, put it at the beginning |
---|
| 560 | LL_Unshift(list, add); |
---|
| 561 | |
---|
| 562 | return 0; |
---|
| 563 | } |
---|
| 564 | |
---|
| 565 | |
---|
| 566 | |
---|
| 567 | ////////////////////////////////////////////////////////////////////// |
---|
| 568 | int LL_SwapNodes(LL_node *one, LL_node *two) // Switch two nodes positions... |
---|
| 569 | { |
---|
| 570 | LL_node *firstprev, *firstnext; |
---|
| 571 | LL_node *secondprev, *secondnext; |
---|
| 572 | |
---|
| 573 | if(!one || !two) return -1; |
---|
| 574 | if(one == two) return 0; // Do nothing |
---|
| 575 | |
---|
| 576 | firstprev = one->prev; // Look up the nodes neighbors... |
---|
| 577 | firstnext = one->next; |
---|
| 578 | secondprev = two->prev; |
---|
| 579 | secondnext = two->next; |
---|
| 580 | |
---|
| 581 | if(firstprev != NULL) firstprev->next = two; // Swap the neighboring |
---|
| 582 | if(firstnext != NULL) firstnext->prev = two; // nodes pointers... |
---|
| 583 | if(secondprev != NULL) secondprev->next = one; |
---|
| 584 | if(secondprev != NULL) secondnext->prev = one; |
---|
| 585 | |
---|
| 586 | one->next = secondnext; // Swap the nodes pointers |
---|
| 587 | one->prev = secondprev; |
---|
| 588 | two->next = firstnext; |
---|
| 589 | two->prev = firstprev; |
---|
| 590 | |
---|
| 591 | if(firstnext == two) one->prev = two; // Fix things in case |
---|
| 592 | if(firstprev == two) one->next = two; // they were next to |
---|
| 593 | if(secondprev == one) two->next = one; // each other... |
---|
| 594 | if(secondnext == one) two->prev = one; |
---|
| 595 | |
---|
| 596 | |
---|
| 597 | return 0; |
---|
| 598 | |
---|
| 599 | } |
---|
| 600 | ////////////////////////////////////////////////////////////////////// |
---|
| 601 | int LL_nSwapNodes(int one, int two) // Switch two nodes positions... |
---|
| 602 | { |
---|
| 603 | return -1; |
---|
| 604 | } |
---|
| 605 | |
---|
| 606 | ////////////////////////////////////////////////////////////////////// |
---|
| 607 | int LL_Length(LL *list) // Returns # of nodes in entire list |
---|
| 608 | { |
---|
| 609 | LL_node *node; |
---|
| 610 | int num = 0; |
---|
| 611 | |
---|
| 612 | if(!list) return -1; |
---|
| 613 | |
---|
| 614 | node = &list->head; |
---|
| 615 | |
---|
| 616 | for(num = -1; |
---|
| 617 | node != &list->tail; |
---|
| 618 | num++) |
---|
| 619 | node = node->next; |
---|
| 620 | |
---|
| 621 | return num; |
---|
| 622 | } |
---|
| 623 | |
---|
| 624 | ////////////////////////////////////////////////////////////////////// |
---|
| 625 | // Searching... |
---|
| 626 | // Goes to the list item which matches "value", and returns the |
---|
| 627 | // data found there. |
---|
| 628 | // |
---|
| 629 | // The "compare" function should return 0 for a "match" |
---|
| 630 | // |
---|
| 631 | // Note that this does *not* rewind the list first! You should do |
---|
| 632 | // it yourself if you want to start from the beginning! |
---|
| 633 | void * LL_Find(LL *list, int compare(void *, void *), void *value) |
---|
| 634 | { |
---|
| 635 | void *data; |
---|
| 636 | |
---|
| 637 | if(!list) return NULL; |
---|
| 638 | if(!compare) return NULL; |
---|
| 639 | if(!value) return NULL; |
---|
| 640 | |
---|
| 641 | do{ |
---|
| 642 | data = LL_Get(list); |
---|
| 643 | if( 0 == compare(data, value) ) return data; |
---|
| 644 | |
---|
| 645 | } while(LL_Next(list) == 0); |
---|
| 646 | |
---|
| 647 | return NULL; |
---|
| 648 | } |
---|
| 649 | |
---|
| 650 | |
---|
| 651 | ////////////////////////////////////////////////////////////////////// |
---|
| 652 | // Sorts the list, then rewinds it... |
---|
| 653 | // |
---|
| 654 | int LL_Sort(LL *list, int compare(void *, void *)) |
---|
| 655 | { |
---|
| 656 | int i,j; // Junk / loop variables |
---|
| 657 | int numnodes; // number of nodes in list |
---|
| 658 | LL_node *best, *last; // best match and last node in the list |
---|
| 659 | LL_node *current; |
---|
| 660 | |
---|
| 661 | |
---|
| 662 | if(!list) return -1; |
---|
| 663 | if(!compare) return -1; |
---|
| 664 | |
---|
| 665 | numnodes = LL_Length(list); // get the number of nodes... |
---|
| 666 | if(0 > LL_End(list)) return -1; // Find the last node. |
---|
| 667 | last = LL_GetNode(list); |
---|
| 668 | |
---|
| 669 | if(numnodes < 2) return 0; |
---|
| 670 | |
---|
| 671 | |
---|
| 672 | for(i=numnodes-1; i>0; i--) |
---|
| 673 | { |
---|
| 674 | LL_Rewind(list); // get the first node again |
---|
| 675 | best = last; // reset our "best" node |
---|
| 676 | |
---|
| 677 | for(j=0; j<i; j++) |
---|
| 678 | { |
---|
| 679 | current = LL_GetNode(list); |
---|
| 680 | // If we found a better match... |
---|
| 681 | if(compare(current->data, best->data) > 0) |
---|
| 682 | { |
---|
| 683 | best = current; // keep track of the "best" match |
---|
| 684 | } |
---|
| 685 | LL_Next(list); // Go to the next node. |
---|
| 686 | } |
---|
| 687 | |
---|
| 688 | LL_SwapNodes(last, best); // Switch two nodes... |
---|
| 689 | if(best) last = best->prev; |
---|
| 690 | else return -1; |
---|
| 691 | |
---|
| 692 | //last = LL_FindPrev(best); // And go backwards by one node. |
---|
| 693 | } |
---|
| 694 | |
---|
| 695 | //return LLFindFirst(current); // return pointer to the first node. |
---|
| 696 | LL_Rewind(list); |
---|
| 697 | |
---|
| 698 | return 0; |
---|
| 699 | |
---|
| 700 | } |
---|
| 701 | |
---|
| 702 | void LL_dprint(LL *list) |
---|
| 703 | { |
---|
| 704 | LL_node *current; |
---|
| 705 | |
---|
| 706 | current = &list->head; |
---|
| 707 | |
---|
| 708 | printf("Head: prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n", |
---|
| 709 | (int)list->head.prev, |
---|
| 710 | (int)&list->head, |
---|
| 711 | (int)list->head.next); |
---|
| 712 | |
---|
| 713 | for(current = current->next; |
---|
| 714 | current != &list->tail; |
---|
| 715 | current = current->next) |
---|
| 716 | { |
---|
| 717 | printf("node: prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n", |
---|
| 718 | (int)current->prev, |
---|
| 719 | (int)current, |
---|
| 720 | (int)current->next); |
---|
| 721 | |
---|
| 722 | } |
---|
| 723 | |
---|
| 724 | printf("Tail: prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n", |
---|
| 725 | (int)list->tail.prev, |
---|
| 726 | (int)&list->tail, |
---|
| 727 | (int)list->tail.next); |
---|
| 728 | } |
---|