diff options
| author | Thomas Schmucker <ts@its1.de> | 2020-08-02 10:55:59 +0200 |
|---|---|---|
| committer | Thomas Schmucker <ts@its1.de> | 2020-08-02 10:55:59 +0200 |
| commit | 09a96907962ac2d1115f545e194f06ea4fd3db19 (patch) | |
| tree | 5df107d0f820b024795ebe3283fa48298c67d2f0 /dlist.c | |
| parent | e7986e3e11b9ca91079bacae7fc2f79dce515f5d (diff) | |
| download | data-structures-09a96907962ac2d1115f545e194f06ea4fd3db19.tar.gz data-structures-09a96907962ac2d1115f545e194f06ea4fd3db19.tar.bz2 data-structures-09a96907962ac2d1115f545e194f06ea4fd3db19.zip | |
reformat codedlist_sort_xxx
Diffstat (limited to 'dlist.c')
| -rw-r--r-- | dlist.c | 151 |
1 files changed, 83 insertions, 68 deletions
| @@ -1,10 +1,10 @@ | |||
| 1 | /* dlist -- double linked list */ | 1 | /* dlist -- double linked list */ |
| 2 | 2 | ||
| 3 | /* Standard C */ | 3 | /* Standard C */ |
| 4 | #include <assert.h> | ||
| 5 | #include <stdbool.h> | ||
| 4 | #include <stdio.h> | 6 | #include <stdio.h> |
| 5 | #include <stdlib.h> | 7 | #include <stdlib.h> |
| 6 | #include <stdbool.h> | ||
| 7 | #include <assert.h> | ||
| 8 | #include <time.h> | 8 | #include <time.h> |
| 9 | 9 | ||
| 10 | /* Project */ | 10 | /* Project */ |
| @@ -18,7 +18,7 @@ struct dlist { | |||
| 18 | 18 | ||
| 19 | struct dlist_element { | 19 | struct dlist_element { |
| 20 | struct dlist_element *prev, *next; | 20 | struct dlist_element *prev, *next; |
| 21 | T data; | 21 | T data; |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | void | 24 | void |
| @@ -32,7 +32,7 @@ static struct dlist_element * | |||
| 32 | create_element(T data) | 32 | create_element(T data) |
| 33 | { | 33 | { |
| 34 | struct dlist_element *element; | 34 | struct dlist_element *element; |
| 35 | 35 | ||
| 36 | element = malloc(sizeof *element); | 36 | element = malloc(sizeof *element); |
| 37 | if ( element != NULL ) { | 37 | if ( element != NULL ) { |
| 38 | element->data = data; | 38 | element->data = data; |
| @@ -45,21 +45,21 @@ struct dlist_element * | |||
| 45 | dlist_push_front(struct dlist *dlist, T data) | 45 | dlist_push_front(struct dlist *dlist, T data) |
| 46 | { | 46 | { |
| 47 | struct dlist_element *element; | 47 | struct dlist_element *element; |
| 48 | 48 | ||
| 49 | element = create_element(data); | 49 | element = create_element(data); |
| 50 | if ( element != NULL ) { | 50 | if ( element != NULL ) { |
| 51 | element->prev = NULL; /* Vorgänger ist in jedem Fall NULL */ | 51 | element->prev = NULL; /* Vorgänger ist in jedem Fall NULL */ |
| 52 | 52 | ||
| 53 | if ( dlist->head == NULL ) { /* empty list */ | 53 | if ( dlist->head == NULL ) { /* empty list */ |
| 54 | element->next = NULL; | 54 | element->next = NULL; |
| 55 | dlist->tail = element; | 55 | dlist->tail = element; |
| 56 | } | 56 | } |
| 57 | else { /* non empty list */ | 57 | else { /* non empty list */ |
| 58 | element->next = dlist->head; | 58 | element->next = dlist->head; |
| 59 | element->next->prev = element; | 59 | element->next->prev = element; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | dlist->head = element; /* Neues Element ist in jedem Fall der neue Anfang! */ | 62 | dlist->head = element; /* Neues Element ist in jedem Fall der neue Anfang! */ |
| 63 | } | 63 | } |
| 64 | else | 64 | else |
| 65 | ERROR("out of memory"); | 65 | ERROR("out of memory"); |
| @@ -71,21 +71,21 @@ struct dlist_element * | |||
| 71 | dlist_push_back(struct dlist *dlist, T data) | 71 | dlist_push_back(struct dlist *dlist, T data) |
| 72 | { | 72 | { |
| 73 | struct dlist_element *element; | 73 | struct dlist_element *element; |
| 74 | 74 | ||
| 75 | element = create_element(data); | 75 | element = create_element(data); |
| 76 | if ( element != NULL ) { | 76 | if ( element != NULL ) { |
| 77 | element->next = NULL; /* Nachfolger ist in jedem Fall NULL */ | 77 | element->next = NULL; /* Nachfolger ist in jedem Fall NULL */ |
| 78 | 78 | ||
| 79 | if ( dlist->head == NULL ) { /* empty list */ | 79 | if ( dlist->head == NULL ) { /* empty list */ |
| 80 | element->prev = NULL; | 80 | element->prev = NULL; |
| 81 | dlist->head = element; | 81 | dlist->head = element; |
| 82 | } | 82 | } |
| 83 | else { /* non empty list */ | 83 | else { /* non empty list */ |
| 84 | element->prev = dlist->tail; | 84 | element->prev = dlist->tail; |
| 85 | element->prev->next = element; | 85 | element->prev->next = element; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | dlist->tail = element; /* Neues Element ist in jedem Fall das neue Ende! */ | 88 | dlist->tail = element; /* Neues Element ist in jedem Fall das neue Ende! */ |
| 89 | } | 89 | } |
| 90 | else | 90 | else |
| 91 | ERROR("out of memory"); | 91 | ERROR("out of memory"); |
| @@ -141,14 +141,14 @@ struct dlist_element * | |||
| 141 | dlist_insert_next(struct dlist *dlist, struct dlist_element *element, T data) | 141 | dlist_insert_next(struct dlist *dlist, struct dlist_element *element, T data) |
| 142 | { | 142 | { |
| 143 | struct dlist_element *new_element; | 143 | struct dlist_element *new_element; |
| 144 | 144 | ||
| 145 | new_element = create_element(data); | 145 | new_element = create_element(data); |
| 146 | if ( new_element != NULL ) { | 146 | if ( new_element != NULL ) { |
| 147 | if ( dlist->head == NULL ) { | 147 | if ( dlist->head == NULL ) { |
| 148 | dlist->head = new_element; | 148 | dlist->head = new_element; |
| 149 | dlist->head->prev = NULL; | 149 | dlist->head->prev = NULL; |
| 150 | dlist->head->next = NULL; | 150 | dlist->head->next = NULL; |
| 151 | dlist->tail = new_element; | 151 | dlist->tail = new_element; |
| 152 | } | 152 | } |
| 153 | else { | 153 | else { |
| 154 | new_element->next = element->next; | 154 | new_element->next = element->next; |
| @@ -172,14 +172,14 @@ struct dlist_element * | |||
| 172 | dlist_insert_prev(struct dlist *dlist, struct dlist_element *element, T data) | 172 | dlist_insert_prev(struct dlist *dlist, struct dlist_element *element, T data) |
| 173 | { | 173 | { |
| 174 | struct dlist_element *new_element; | 174 | struct dlist_element *new_element; |
| 175 | 175 | ||
| 176 | new_element = create_element(data); | 176 | new_element = create_element(data); |
| 177 | if ( new_element != NULL ) { | 177 | if ( new_element != NULL ) { |
| 178 | if ( dlist->head == NULL ) { | 178 | if ( dlist->head == NULL ) { |
| 179 | dlist->head = new_element; | 179 | dlist->head = new_element; |
| 180 | dlist->head->prev = NULL; | 180 | dlist->head->prev = NULL; |
| 181 | dlist->head->next = NULL; | 181 | dlist->head->next = NULL; |
| 182 | dlist->tail = new_element; | 182 | dlist->tail = new_element; |
| 183 | } | 183 | } |
| 184 | else { | 184 | else { |
| 185 | new_element->next = element; | 185 | new_element->next = element; |
| @@ -226,7 +226,7 @@ void | |||
| 226 | dlist_free(struct dlist *dlist) | 226 | dlist_free(struct dlist *dlist) |
| 227 | { | 227 | { |
| 228 | struct dlist_element *elem, *next; | 228 | struct dlist_element *elem, *next; |
| 229 | 229 | ||
| 230 | for ( elem = dlist->head; elem; elem = next ) { | 230 | for ( elem = dlist->head; elem; elem = next ) { |
| 231 | next = elem->next; | 231 | next = elem->next; |
| 232 | free(elem); | 232 | free(elem); |
| @@ -285,60 +285,71 @@ dlist_sort_xxx(struct dlist *list) | |||
| 285 | 285 | ||
| 286 | int insize = 1; | 286 | int insize = 1; |
| 287 | 287 | ||
| 288 | while (1) { | 288 | while ( 1 ) { |
| 289 | struct dlist_element *p; | 289 | struct dlist_element *p; |
| 290 | 290 | ||
| 291 | p = list->head; | 291 | p = list->head; |
| 292 | list->head = NULL; | 292 | list->head = NULL; |
| 293 | list->tail = NULL; | 293 | list->tail = NULL; |
| 294 | 294 | ||
| 295 | int nmerges = 0; /* count number of merges we do in this pass */ | 295 | int nmerges = 0; /* count number of merges we do in this pass */ |
| 296 | |||
| 297 | while (p) { | ||
| 298 | 296 | ||
| 297 | while ( p ) { | ||
| 299 | struct dlist_element *q; | 298 | struct dlist_element *q; |
| 300 | 299 | ||
| 301 | nmerges++; /* there exists a merge to be done */ | 300 | nmerges++; /* there exists a merge to be done */ |
| 302 | /* step `insize' places along from p */ | 301 | /* step `insize' places along from p */ |
| 303 | q = p; | 302 | q = p; |
| 304 | int psize = 0; | 303 | int psize = 0; |
| 305 | for (int i = 0; i < insize; i++) { | 304 | for ( int i = 0; i < insize; i++ ) { |
| 306 | psize++; | 305 | psize++; |
| 307 | q = q->next; | 306 | q = q->next; |
| 308 | if (!q) break; | 307 | if ( !q ) |
| 308 | break; | ||
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | /* if q hasn't fallen off end, we have two lists to merge */ | 311 | /* if q hasn't fallen off end, we have two lists to merge */ |
| 312 | int qsize = insize; | 312 | int qsize = insize; |
| 313 | 313 | ||
| 314 | /* now we have two lists; merge them */ | 314 | /* now we have two lists; merge them */ |
| 315 | while (psize > 0 || (qsize > 0 && q)) { | 315 | while ( psize > 0 || (qsize > 0 && q) ) { |
| 316 | |||
| 317 | struct dlist_element *e; | 316 | struct dlist_element *e; |
| 318 | 317 | ||
| 319 | /* decide whether next element of merge comes from p or q */ | 318 | /* decide whether next element of merge comes from p or q */ |
| 320 | if (psize == 0) { | 319 | if ( psize == 0 ) { |
| 321 | /* p is empty; e must come from q. */ | 320 | /* p is empty; e must come from q. */ |
| 322 | e = q; q = q->next; qsize--; | 321 | e = q; |
| 323 | } else if (qsize == 0 || !q) { | 322 | q = q->next; |
| 323 | qsize--; | ||
| 324 | } | ||
| 325 | else if ( qsize == 0 || !q ) { | ||
| 324 | /* q is empty; e must come from p. */ | 326 | /* q is empty; e must come from p. */ |
| 325 | e = p; p = p->next; psize--; | 327 | e = p; |
| 326 | } else if (p->data < q->data) { | 328 | p = p->next; |
| 329 | psize--; | ||
| 330 | } | ||
| 331 | else if ( p->data < q->data ) { | ||
| 327 | /* First element of p is lower ; | 332 | /* First element of p is lower ; |
| 328 | * e must come from p. */ | 333 | * e must come from p. */ |
| 329 | e = p; p = p->next; psize--; | 334 | e = p; |
| 330 | } else { | 335 | p = p->next; |
| 336 | psize--; | ||
| 337 | } | ||
| 338 | else { | ||
| 331 | /* First element of q is lower; e must come from q. */ | 339 | /* First element of q is lower; e must come from q. */ |
| 332 | e = q; q = q->next; qsize--; | 340 | e = q; |
| 341 | q = q->next; | ||
| 342 | qsize--; | ||
| 333 | } | 343 | } |
| 334 | 344 | ||
| 335 | /* add the next element to the merged list */ | 345 | /* add the next element to the merged list */ |
| 336 | if (list->tail) { | 346 | if ( list->tail ) { |
| 337 | list->tail->next = e; | 347 | list->tail->next = e; |
| 338 | } else { | 348 | } |
| 349 | else { | ||
| 339 | list->head = e; | 350 | list->head = e; |
| 340 | } | 351 | } |
| 341 | e->prev = list->tail; | 352 | e->prev = list->tail; |
| 342 | list->tail = e; | 353 | list->tail = e; |
| 343 | } | 354 | } |
| 344 | 355 | ||
| @@ -348,8 +359,8 @@ dlist_sort_xxx(struct dlist *list) | |||
| 348 | list->tail->next = NULL; | 359 | list->tail->next = NULL; |
| 349 | 360 | ||
| 350 | /* If we have done only one merge, we're finished. */ | 361 | /* If we have done only one merge, we're finished. */ |
| 351 | if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ | 362 | if ( nmerges <= 1 ) /* allow for nmerges==0, the empty list case */ |
| 352 | return; // list; | 363 | return; // list; |
| 353 | 364 | ||
| 354 | /* Otherwise repeat, merging lists twice the size */ | 365 | /* Otherwise repeat, merging lists twice the size */ |
| 355 | insize *= 2; | 366 | insize *= 2; |
| @@ -364,31 +375,29 @@ dlist_merge(struct dlist *list1, struct dlist *list2) | |||
| 364 | *e1 = list1->head, | 375 | *e1 = list1->head, |
| 365 | *e2 = list2->head; | 376 | *e2 = list2->head; |
| 366 | 377 | ||
| 367 | while ( e1 != NULL && e2 != NULL ) // Solange in e1 UND e2 Elemente sind... | 378 | while ( e1 != NULL && e2 != NULL ) // Solange in e1 UND e2 Elemente sind... |
| 368 | { | 379 | { |
| 369 | if ( e1->data < e2->data ) | 380 | if ( e1->data < e2->data ) { |
| 370 | { | ||
| 371 | e1->prev = cur; | 381 | e1->prev = cur; |
| 372 | if ( cur != NULL ) | 382 | if ( cur != NULL ) |
| 373 | cur->next = e1; | 383 | cur->next = e1; |
| 374 | else | 384 | else |
| 375 | head = e1; | 385 | head = e1; |
| 376 | cur = e1; | 386 | cur = e1; |
| 377 | e1 = e1->next; | 387 | e1 = e1->next; |
| 378 | } | 388 | } |
| 379 | else | 389 | else { |
| 380 | { | ||
| 381 | e2->prev = cur; | 390 | e2->prev = cur; |
| 382 | if ( cur != NULL ) | 391 | if ( cur != NULL ) |
| 383 | cur->next = e2; | 392 | cur->next = e2; |
| 384 | else | 393 | else |
| 385 | head = e2; | 394 | head = e2; |
| 386 | cur = e2; | 395 | cur = e2; |
| 387 | e2 = e2->next; | 396 | e2 = e2->next; |
| 388 | } | 397 | } |
| 389 | } | 398 | } |
| 390 | 399 | ||
| 391 | if ( e1 != NULL ) // in e1 sind noch Elemente vorhanden! | 400 | if ( e1 != NULL ) // in e1 sind noch Elemente vorhanden! |
| 392 | { | 401 | { |
| 393 | assert(e2 == NULL); | 402 | assert(e2 == NULL); |
| 394 | 403 | ||
| @@ -411,7 +420,7 @@ dlist_merge(struct dlist *list1, struct dlist *list2) | |||
| 411 | else | 420 | else |
| 412 | head = e2; | 421 | head = e2; |
| 413 | 422 | ||
| 414 | list1->tail = list2->tail; // list2->tail ist das Ende der Liste | 423 | list1->tail = list2->tail; // list2->tail ist das Ende der Liste |
| 415 | } | 424 | } |
| 416 | 425 | ||
| 417 | // Kopf neu setzen... | 426 | // Kopf neu setzen... |
| @@ -428,17 +437,17 @@ dlist_merge(struct dlist *list1, struct dlist *list2) | |||
| 428 | struct dlist * | 437 | struct dlist * |
| 429 | dlist_sort(struct dlist *list) | 438 | dlist_sort(struct dlist *list) |
| 430 | { | 439 | { |
| 431 | if ( list->head == NULL || list->head->next == NULL ) // Leer oder nur ein Element? => Fertig | 440 | if ( list->head == NULL || list->head->next == NULL ) // Leer oder nur ein Element? => Fertig |
| 432 | return list; | 441 | return list; |
| 433 | 442 | ||
| 434 | struct dlist_element *slow = list->head, | 443 | struct dlist_element *slow = list->head, |
| 435 | *fast = list->head->next; | 444 | *fast = list->head->next; |
| 436 | 445 | ||
| 437 | while ( fast != NULL && fast->next != NULL ) | 446 | while ( fast != NULL && fast->next != NULL ) |
| 438 | slow = slow->next, fast = fast->next->next; | 447 | slow = slow->next, fast = fast->next->next; |
| 439 | 448 | ||
| 440 | struct dlist list1 = { .head = list->head, .tail = slow }, | 449 | struct dlist list1 = { .head = list->head, .tail = slow }, |
| 441 | list2 = { .head = slow->next, .tail = list->tail }; | 450 | list2 = { .head = slow->next, .tail = list->tail }; |
| 442 | 451 | ||
| 443 | list1.tail->next = list2.head->prev = NULL; | 452 | list1.tail->next = list2.head->prev = NULL; |
| 444 | 453 | ||
| @@ -450,7 +459,8 @@ dlist_sort(struct dlist *list) | |||
| 450 | return list; | 459 | return list; |
| 451 | } | 460 | } |
| 452 | 461 | ||
| 453 | void merge_test(void) | 462 | void |
| 463 | merge_test(void) | ||
| 454 | { | 464 | { |
| 455 | struct dlist l1, l2; | 465 | struct dlist l1, l2; |
| 456 | 466 | ||
| @@ -472,9 +482,15 @@ void merge_test(void) | |||
| 472 | 482 | ||
| 473 | struct dlist_element *cur; | 483 | struct dlist_element *cur; |
| 474 | for ( cur = ptr->head; cur; cur = cur->next ) { | 484 | for ( cur = ptr->head; cur; cur = cur->next ) { |
| 475 | if ( cur->prev ) printf("%4d", cur->prev->data); else printf("xxx "); | 485 | if ( cur->prev ) |
| 486 | printf("%4d", cur->prev->data); | ||
| 487 | else | ||
| 488 | printf("xxx "); | ||
| 476 | printf("%4d", cur->data); | 489 | printf("%4d", cur->data); |
| 477 | if ( cur->next ) printf("%4d", cur->next->data); else printf(" xxx"); | 490 | if ( cur->next ) |
| 491 | printf("%4d", cur->next->data); | ||
| 492 | else | ||
| 493 | printf(" xxx"); | ||
| 478 | 494 | ||
| 479 | puts(""); | 495 | puts(""); |
| 480 | } | 496 | } |
| @@ -483,7 +499,8 @@ void merge_test(void) | |||
| 483 | dlist_free(&l2); | 499 | dlist_free(&l2); |
| 484 | } | 500 | } |
| 485 | 501 | ||
| 486 | void ls() | 502 | void |
| 503 | ls() | ||
| 487 | { | 504 | { |
| 488 | struct dlist list; | 505 | struct dlist list; |
| 489 | 506 | ||
| @@ -498,14 +515,13 @@ void ls() | |||
| 498 | dlist_sort(&list); | 515 | dlist_sort(&list); |
| 499 | clock_t ende = clock(); | 516 | clock_t ende = clock(); |
| 500 | 517 | ||
| 501 | printf("Dauer: %.3fsec\n", ((double) ende-start)/CLOCKS_PER_SEC); | 518 | printf("Dauer: %.3fsec\n", ((double) ende - start) / CLOCKS_PER_SEC); |
| 502 | //print_list("Sortiert:", &list); | 519 | //print_list("Sortiert:", &list); |
| 503 | //print_list_rev("Sortiert:", &list); | 520 | //print_list_rev("Sortiert:", &list); |
| 504 | 521 | ||
| 505 | dlist_free(&list); | 522 | dlist_free(&list); |
| 506 | } | 523 | } |
| 507 | 524 | ||
| 508 | |||
| 509 | int | 525 | int |
| 510 | main(void) | 526 | main(void) |
| 511 | { | 527 | { |
| @@ -536,4 +552,3 @@ main(void) | |||
| 536 | return EXIT_SUCCESS; | 552 | return EXIT_SUCCESS; |
| 537 | #endif | 553 | #endif |
| 538 | } | 554 | } |
| 539 | |||
