@@ -294,95 +294,145 @@ void q_reverseK(struct list_head *head, int k)
294
294
}
295
295
296
296
/* Start of sort */
297
- typedef int (* compare_func_t )(struct list_head * , struct list_head * );
297
+ typedef int (* list_cmp_func_t )(const struct list_head * ,
298
+ const struct list_head * );
298
299
299
- /* Sort elements of queue in ascending/descending order */
300
- static int cmp_func (struct list_head * a , struct list_head * b )
300
+ static int cmp (const struct list_head * a , const struct list_head * b )
301
301
{
302
302
const element_t * element_a = list_entry (a , element_t , list );
303
303
const element_t * element_b = list_entry (b , element_t , list );
304
304
return strcmp (element_a -> value , element_b -> value );
305
305
}
306
306
307
- static struct list_head * merge_list (struct list_head * first ,
308
- struct list_head * second ,
309
- compare_func_t cmp )
307
+ typedef int (* compare_func_t )(struct list_head * , struct list_head * );
308
+
309
+ static struct list_head * merge (list_cmp_func_t cmp ,
310
+ struct list_head * a ,
311
+ struct list_head * b )
310
312
{
311
- struct list_head dummy ;
312
- struct list_head * tail = & dummy ;
313
- dummy .next = NULL ;
314
-
315
- while (first && second ) {
316
- if (cmp (first , second ) <= 0 ) {
317
- tail -> next = first ;
318
- first -> prev = tail ;
319
- first = first -> next ;
313
+ struct list_head * head = NULL , * * tail = & head ;
314
+
315
+ for (;;) {
316
+ /* if equal, take 'a' -- important for sort stability */
317
+ if (cmp (a , b ) <= 0 ) {
318
+ * tail = a ;
319
+ tail = & a -> next ;
320
+ a = a -> next ;
321
+ if (!a ) {
322
+ * tail = b ;
323
+ break ;
324
+ }
320
325
} else {
321
- tail -> next = second ;
322
- second -> prev = tail ;
323
- second = second -> next ;
326
+ * tail = b ;
327
+ tail = & b -> next ;
328
+ b = b -> next ;
329
+ if (!b ) {
330
+ * tail = a ;
331
+ break ;
332
+ }
324
333
}
325
- tail = tail -> next ;
326
334
}
327
-
328
- tail -> next = (first ? first : second );
329
- if (tail -> next ) {
330
- tail -> next -> prev = tail ;
331
- }
332
- return dummy .next ;
335
+ return head ;
333
336
}
334
337
335
- static struct list_head * merge_two_list (struct list_head * head ,
336
- compare_func_t cmp )
338
+ static void merge_final (list_cmp_func_t cmp ,
339
+ struct list_head * head ,
340
+ struct list_head * a ,
341
+ struct list_head * b )
337
342
{
338
- if (!head || !head -> next ) {
339
- return head ;
340
- }
341
-
342
- struct list_head * slow = head ;
343
- struct list_head * fast = head -> next ;
344
-
345
- while (fast && fast -> next ) {
346
- slow = slow -> next ;
347
- fast = fast -> next -> next ;
348
- }
349
- struct list_head * second = slow -> next ;
350
- slow -> next = NULL ;
351
- if (second ) {
352
- second -> prev = NULL ;
343
+ struct list_head * tail = head ;
344
+ unsigned char count = 0 ;
345
+
346
+ for (;;) {
347
+ /* if equal, take 'a' -- important for sort stability */
348
+ if (cmp (a , b ) <= 0 ) {
349
+ tail -> next = a ;
350
+ a -> prev = tail ;
351
+ tail = a ;
352
+ a = a -> next ;
353
+ if (!a )
354
+ break ;
355
+ } else {
356
+ tail -> next = b ;
357
+ b -> prev = tail ;
358
+ tail = b ;
359
+ b = b -> next ;
360
+ if (!b ) {
361
+ b = a ;
362
+ break ;
363
+ }
364
+ }
353
365
}
354
366
355
- head = merge_two_list (head , cmp );
356
- second = merge_two_list (second , cmp );
367
+ /* Finish linking remainder of list b on to tail */
368
+ tail -> next = b ;
369
+ do {
370
+ if (__glibc_unlikely (!++ count ))
371
+ cmp (b , b );
372
+ b -> prev = tail ;
373
+ tail = b ;
374
+ b = b -> next ;
375
+ } while (b );
357
376
358
- return merge_list (head , second , cmp );
377
+ /* And the final links to make a circular doubly-linked list */
378
+ tail -> next = head ;
379
+ head -> prev = tail ;
359
380
}
360
381
361
- void merge_sort (struct list_head * head , compare_func_t cmp )
382
+ void list_sort (struct list_head * head , list_cmp_func_t cmp )
362
383
{
363
- if (!head || list_empty (head ) || head -> next -> next == head ) {
384
+ struct list_head * list = head -> next , * pending = NULL ;
385
+ size_t count = 0 ; /* Count of pending */
386
+
387
+ if (list == head -> prev ) /* Zero or one elements */
364
388
return ;
365
- }
366
389
367
- struct list_head * first = head -> next ;
368
- first -> prev -> next = NULL ;
390
+ /* Convert to a null-terminated singly-linked list. */
369
391
head -> prev -> next = NULL ;
370
392
371
- first = merge_two_list (first , cmp );
393
+ do {
394
+ size_t bits ;
395
+ struct list_head * * tail = & pending ;
396
+
397
+ /* Find the least-significant clear bit in count */
398
+ for (bits = count ; bits & 1 ; bits >>= 1 )
399
+ tail = & (* tail )-> prev ;
400
+ /* Do the indicated merge */
401
+ if (__glibc_likely (bits )) {
402
+ struct list_head * a = * tail , * b = a -> prev ;
403
+
404
+ a = merge (cmp , b , a );
405
+ /* Install the merged result in place of the inputs */
406
+ a -> prev = b -> prev ;
407
+ * tail = a ;
408
+ }
372
409
373
- struct list_head * tail = first ;
374
- while (tail -> next ) {
375
- tail = tail -> next ;
410
+ /* Move one element from input list to pending */
411
+ list -> prev = pending ;
412
+ pending = list ;
413
+ list = list -> next ;
414
+ pending -> next = NULL ;
415
+ count ++ ;
416
+ } while (list );
417
+
418
+ /* End of input; merge together all the pending lists. */
419
+ list = pending ;
420
+ pending = pending -> prev ;
421
+ for (;;) {
422
+ struct list_head * next = pending -> prev ;
423
+
424
+ if (!next )
425
+ break ;
426
+ list = merge (cmp , pending , list );
427
+ pending = next ;
376
428
}
377
- head -> next = first ;
378
- first -> prev = head ;
379
- tail -> next = head ;
380
- head -> prev = tail ;
429
+ /* The final merge, rebuilding prev links */
430
+ merge_final (cmp , head , pending , list );
381
431
}
382
432
383
433
void q_sort (struct list_head * head , bool descend )
384
434
{
385
- merge_sort (head , cmp_func );
435
+ list_sort (head , cmp );
386
436
387
437
if (descend ) {
388
438
q_reverse (head );
0 commit comments