Skip to content

Commit dfe3862

Browse files
committed
Implement sort, ascend, and descend functions
Add q_sort to sort queue elements in ascending or descending order using merge sort, ensuring O(n log n) time complexity. This implementation maintains stable sorting to preserve the relative order of duplicate elements. Add q_ascend to remove every node that has a strictly smaller node to its right, ensuring that the remaining list is strictly increasing. This is implemented using a single pass with O(n) complexity. Add q_descend to remove every node that has a strictly greater node to its right, ensuring that the remaining list is strictly decreasing. This mirrors the logic of q_ascend and also runs in O(n) time. Change-Id: Icfcadf3b18aa015b12d23d7f13bb2b25096cc086
1 parent 97d2cb0 commit dfe3862

File tree

1 file changed

+119
-5
lines changed

1 file changed

+119
-5
lines changed

queue.c

Lines changed: 119 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
* cppcheck-suppress nullPointer
1111
*/
1212

13+
static struct list_head *merge_sort(struct list_head *head, bool descend);
14+
static struct list_head *merge(struct list_head *l1,
15+
struct list_head *l2,
16+
bool descend);
17+
1318
/* Create an empty queue */
1419
struct list_head *q_new()
1520
{
@@ -75,6 +80,7 @@ bool q_insert_tail(struct list_head *head, char *s)
7580
free(new_node);
7681
return false;
7782
}
83+
INIT_LIST_HEAD(&new_node->list);
7884
list_add_tail(&new_node->list, head);
7985
return true;
8086
}
@@ -273,28 +279,136 @@ void q_reverseK(struct list_head *head, int k)
273279
}
274280

275281
/* Sort elements of queue in ascending/descending order */
276-
void q_sort(struct list_head *head, bool descend) {}
282+
void q_sort(struct list_head *head, bool descend)
283+
{
284+
if (!head || list_empty(head) || head->next == head->prev) {
285+
return;
286+
}
287+
288+
head->prev->next = NULL;
289+
struct list_head *sorted = merge_sort(head->next, descend);
290+
291+
LIST_HEAD(tmp);
292+
list_splice_tail_init(sorted, &tmp);
293+
list_splice_tail_init(&tmp, head);
294+
}
295+
296+
static struct list_head *merge_sort(struct list_head *head, bool descend)
297+
{
298+
if (!head || !head->next)
299+
return head;
300+
301+
struct list_head *slow = head, *fast = head->next;
302+
303+
while (fast && fast->next) {
304+
slow = slow->next;
305+
fast = fast->next->next;
306+
}
307+
308+
struct list_head *mid = slow->next;
309+
slow->next = NULL;
310+
311+
struct list_head *left = merge_sort(head, descend);
312+
struct list_head *right = merge_sort(mid, descend);
313+
314+
return merge(left, right, descend);
315+
}
316+
317+
static struct list_head *merge(struct list_head *l1,
318+
struct list_head *l2,
319+
bool descend)
320+
{
321+
struct list_head dummy;
322+
struct list_head *tail = &dummy;
323+
dummy.next = NULL;
324+
325+
while (l1 && l2) {
326+
const element_t *e1 = list_entry(l1, element_t, list);
327+
const element_t *e2 = list_entry(l2, element_t, list);
328+
329+
bool condition = descend ? (strcmp(e1->value, e2->value) > 0)
330+
: (strcmp(e1->value, e2->value) < 0);
331+
332+
if (condition) {
333+
tail->next = l1;
334+
l1->prev = tail;
335+
l1 = l1->next;
336+
} else {
337+
tail->next = l2;
338+
l2->prev = tail;
339+
l2 = l2->next;
340+
}
341+
342+
tail = tail->next;
343+
}
344+
345+
tail->next = l1 ? l1 : l2;
346+
if (tail->next)
347+
tail->next->prev = tail;
348+
349+
return dummy.next;
350+
}
277351

278352
/* Remove every node which has a node with a strictly less value anywhere to
279353
* the right side of it */
280354
int q_ascend(struct list_head *head)
281355
{
356+
if (!head || list_empty(head) || head->next == head->prev) {
357+
return 0;
358+
}
359+
360+
struct list_head *cur = head->prev, *prev_max = cur, *tmp;
361+
int count = 1;
362+
363+
list_for_each_safe (cur, tmp, head) {
364+
element_t *e_cur = list_entry(cur, element_t, list);
365+
const element_t *e_max = list_entry(prev_max, element_t, list);
366+
367+
if (strcmp(e_cur->value, e_max->value) >= 0) {
368+
prev_max = cur;
369+
count++;
370+
} else {
371+
list_del(cur);
372+
free(e_cur->value);
373+
free(e_cur);
374+
}
375+
}
376+
377+
return count;
282378
// https://leetcode.com/problems/remove-nodes-from-linked-list/
283-
return 0;
284379
}
285380

286381
/* Remove every node which has a node with a strictly greater value anywhere to
287382
* the right side of it */
288383
int q_descend(struct list_head *head)
289384
{
290-
// https://leetcode.com/problems/remove-nodes-from-linked-list/
291-
return 0;
385+
if (!head || list_empty(head) || head->next == head->prev) {
386+
return 0;
387+
}
388+
389+
struct list_head *cur = head->prev, *prev_min = cur, *tmp;
390+
int count = 1;
391+
392+
list_for_each_safe (cur, tmp, head) {
393+
element_t *e_cur = list_entry(cur, element_t, list);
394+
const element_t *e_min = list_entry(prev_min, element_t, list);
395+
396+
if (strcmp(e_cur->value, e_min->value) <= 0) {
397+
prev_min = cur;
398+
count++;
399+
} else {
400+
list_del(cur);
401+
free(e_cur->value);
402+
free(e_cur);
403+
}
404+
}
405+
406+
return count;
292407
}
293408

294409
/* Merge all the queues into one sorted queue, which is in ascending/descending
295410
* order */
296411
int q_merge(struct list_head *head, bool descend)
297412
{
298-
// https://leetcode.com/problems/merge-k-sorted-lists/
299413
return 0;
300414
}

0 commit comments

Comments
 (0)