|
1 | 1 | #include <stdio.h>
|
2 | 2 | #include <stdlib.h>
|
3 |
| -#include <limits.h> |
| 3 | +#include <string.h> |
4 | 4 |
|
5 | 5 | struct ListNode {
|
6 | 6 | int val;
|
7 | 7 | struct ListNode *next;
|
8 | 8 | };
|
9 | 9 |
|
| 10 | +struct PriorityQueue { |
| 11 | + struct ListNode **nodes; |
| 12 | + int size; |
| 13 | +}; |
| 14 | + |
| 15 | +static inline void swap(struct ListNode **a, struct ListNode **b) |
| 16 | +{ |
| 17 | + struct ListNode *tmp = *a; |
| 18 | + *a = *b; |
| 19 | + *b = tmp; |
| 20 | +} |
| 21 | + |
| 22 | +static inline int left(int i) { return i * 2 + 1; } |
| 23 | +static inline int right(int i) { return left(i) + 1; } |
| 24 | +static inline int parent(int i) { return (i - 1) / 2; } |
| 25 | + |
| 26 | +static void queue_dump(struct PriorityQueue *queue) |
| 27 | +{ |
| 28 | + int i; |
| 29 | + for (i = 0; i < queue->size; i++) { |
| 30 | + printf("%d ", queue->nodes[i]->val); |
| 31 | + } |
| 32 | + printf("\n"); |
| 33 | +} |
| 34 | + |
| 35 | +static void percolate_up(struct ListNode **nodes, int i) |
| 36 | +{ |
| 37 | + while (i >= 0 && nodes[parent(i)]->val > nodes[i]->val) { |
| 38 | + swap(nodes + parent(i), nodes + i); |
| 39 | + i = parent(i); |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +static void percolate_down1(struct ListNode **nodes, int size, int child) |
| 44 | +{ |
| 45 | + int i, min; |
| 46 | + for (i = child; i >= 0; i = parent(i)) { |
| 47 | + if (right(i) < size) { |
| 48 | + min = nodes[left(i)]->val < nodes[right(i)]->val ? left(i) : right(i); |
| 49 | + } else { |
| 50 | + min = left(i); |
| 51 | + } |
| 52 | + if (nodes[min]->val < nodes[i]->val) { |
| 53 | + swap(nodes + min, nodes + i); |
| 54 | + } else { |
| 55 | + break; |
| 56 | + } |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +static void percolate_down2(struct ListNode **nodes, int size) |
| 61 | +{ |
| 62 | + int i, min; |
| 63 | + for (i = 0; left(i) < size; i = min) { |
| 64 | + if (right(i) < size) { |
| 65 | + min = nodes[left(i)]->val < nodes[right(i)]->val ? left(i) : right(i); |
| 66 | + } else { |
| 67 | + min = left(i); |
| 68 | + } |
| 69 | + if (nodes[min]->val < nodes[i]->val) { |
| 70 | + swap(nodes + min, nodes + i); |
| 71 | + } else { |
| 72 | + break; |
| 73 | + } |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +static void heap_build(struct PriorityQueue *queue) |
| 78 | +{ |
| 79 | + int i; |
| 80 | + for (i = queue->size / 2 - 1; i > 0; i--) { |
| 81 | + percolate_down1(queue->nodes, queue->size, i); |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +static void put(struct PriorityQueue *queue, struct ListNode *node) |
| 86 | +{ |
| 87 | + queue->nodes[queue->size++] = node; |
| 88 | + percolate_up(queue->nodes, queue->size - 1); |
| 89 | +} |
| 90 | + |
| 91 | +static struct ListNode *get(struct PriorityQueue *queue) |
| 92 | +{ |
| 93 | + int i; |
| 94 | + struct ListNode *p = queue->nodes[0]; |
| 95 | + swap(queue->nodes, queue->nodes + queue->size - 1); |
| 96 | + queue->size--; |
| 97 | + percolate_down2(queue->nodes, queue->size); |
| 98 | + return p; |
| 99 | +} |
| 100 | + |
| 101 | +static struct PriorityQueue *init(int size) |
| 102 | +{ |
| 103 | + struct PriorityQueue *queue = malloc(sizeof(*queue)); |
| 104 | + queue->nodes = malloc(size * sizeof(*queue->nodes)); |
| 105 | + queue->size = 0; |
| 106 | + return queue; |
| 107 | +} |
| 108 | + |
10 | 109 | static struct ListNode* mergeKLists(struct ListNode** lists, int listsSize)
|
11 | 110 | {
|
12 | 111 | if (listsSize == 0) {
|
13 | 112 | return NULL;
|
14 | 113 | }
|
| 114 | + |
15 | 115 | if (listsSize == 1) {
|
16 | 116 | return lists[0];
|
17 | 117 | }
|
18 | 118 |
|
19 |
| - int i, index; |
20 |
| - struct ListNode dummy, *p, *prev; |
| 119 | + int i; |
| 120 | + struct ListNode dummy; |
| 121 | + struct ListNode *prev; |
| 122 | + struct PriorityQueue *queue = init(listsSize); |
21 | 123 |
|
22 | 124 | dummy.next = NULL;
|
23 | 125 | prev = &dummy;
|
24 |
| - index = 0; |
25 |
| - while (index != -1) { |
26 |
| - int min = INT_MAX; |
27 |
| - index = -1; |
28 |
| - for (i = 0; i < listsSize; i++) { |
29 |
| - if (lists[i] != NULL && lists[i]->val < min) { |
30 |
| - min = lists[i]->val; |
31 |
| - index = i; |
32 |
| - } |
| 126 | + |
| 127 | + for (i = 0; i < listsSize; i++) { |
| 128 | + if (lists[i] != NULL) { |
| 129 | + put(queue, lists[i]); |
33 | 130 | }
|
| 131 | + } |
| 132 | + heap_build(queue); |
34 | 133 |
|
35 |
| - if (index != -1) { |
36 |
| - p = malloc(sizeof(*p)); |
37 |
| - p->val = min; |
38 |
| - p->next = NULL; |
39 |
| - prev->next = p; |
40 |
| - prev = p; |
41 |
| - lists[index] = lists[index]->next; |
| 134 | + while (queue->size > 0) { |
| 135 | + struct ListNode *n = get(queue); |
| 136 | + prev->next = n; |
| 137 | + prev = n; |
| 138 | + if (n->next != NULL) { |
| 139 | + put(queue, n->next); |
42 | 140 | }
|
| 141 | + n->next = NULL; |
43 | 142 | }
|
44 | 143 |
|
45 | 144 | return dummy.next;
|
|
0 commit comments