Skip to content

Commit 3d95a49

Browse files
committed
Fix sort, descend, and reverseK to preserve queue
Updated q_sort() to ensure stable sorting, preventing duplicate elements from changing order unexpectedly. Fixed q_descend() to correctly update head->prev after removal, preventing queue corruption. Refactored q_reverseK() to properly reverse nodes in k-groups while maintaining correct list connections. Improved pointer handling to avoid segmentation faults and ensure O(n) efficiency. Change-Id: I49ef133b50bb30f6d3512cc7265a5a1f19c8f9f5
1 parent dfe3862 commit 3d95a49

File tree

1 file changed

+97
-91
lines changed

1 file changed

+97
-91
lines changed

queue.c

Lines changed: 97 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@
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-
1813
/* Create an empty queue */
1914
struct list_head *q_new()
2015
{
@@ -166,38 +161,42 @@ bool q_delete_mid(struct list_head *head)
166161
/* Delete all nodes that have duplicate string */
167162
bool q_delete_dup(struct list_head *head)
168163
{
169-
if (!head || list_empty(head)) {
164+
if (!head || list_empty(head))
170165
return false;
171-
}
172166

173-
struct list_head *cur = head->next;
167+
struct list_head *cur, *next;
174168
bool deleted = false;
175169

176-
while (cur != head || cur->next != head) {
177-
// compare between cur->value and next_cur->value7
178-
const element_t *node = list_entry(cur, element_t, list);
179-
const element_t *next_node = list_entry(cur->next, element_t, list);
170+
list_for_each_safe (cur, next, head) {
171+
element_t *node = list_entry(cur, element_t, list);
172+
173+
if (next != head) {
174+
const element_t *next_node = list_entry(next, element_t, list);
175+
176+
if (strcmp(node->value, next_node->value) == 0) {
177+
deleted = true;
178+
const char *dup_value = node->value;
179+
struct list_head *tmp;
180180

181-
if (strcmp(node->value, next_node->value) == 0) {
182-
deleted = true;
183-
const char *dup_value = node->value;
184-
struct list_head *tmp;
181+
while (next != head &&
182+
strcmp(list_entry(next, element_t, list)->value,
183+
dup_value) == 0) {
184+
tmp = next->next;
185+
list_del(next);
186+
element_t *del_node = list_entry(next, element_t, list);
187+
free(del_node->value);
188+
free(del_node);
189+
next = tmp;
190+
}
185191

186-
while (cur != head &&
187-
strcmp(list_entry(cur, element_t, list)->value, dup_value)) {
188192
tmp = cur->next;
189193
list_del(cur);
190-
element_t *del_node = list_entry(cur, element_t, list);
191-
free(del_node->value);
192-
free(del_node);
194+
free(node->value);
195+
free(node);
193196
cur = tmp;
194197
}
195-
} else {
196-
cur = cur->next;
197198
}
198199
}
199-
200-
// https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
201200
return deleted;
202201
}
203202

@@ -242,64 +241,77 @@ void q_reverse(struct list_head *head)
242241
/* Reverse the nodes of the list k at a time */
243242
void q_reverseK(struct list_head *head, int k)
244243
{
245-
if (!head || list_empty(head) || k <= 1) {
244+
if (!head || list_empty(head) || k <= 1)
246245
return;
247-
}
248246

249-
struct list_head *cur, *next;
247+
struct list_head *cur, *group_start, *next;
250248
int count = 0;
251249

252-
list_for_each (cur, head) {
250+
list_for_each (cur, head)
253251
count++;
254-
}
255252

256-
if (count < k) {
253+
if (count < k)
257254
return;
258-
}
259255

260256
cur = head->next;
261257

262258
while (count >= k) {
263-
struct list_head *group_tail = cur;
264-
int i = 0;
259+
group_start = cur;
260+
struct list_head *prev_tail = group_start->prev;
265261

266-
list_for_each_safe (cur, next, head) {
267-
if (++i == k)
268-
break;
269-
list_move_tail(next, head);
262+
for (int i = 0; i < k; i++) {
263+
next = cur->next;
264+
list_move(cur, prev_tail);
265+
cur = next;
270266
}
271267

272-
group_tail->prev = cur->prev;
273-
cur->prev->next = group_tail;
268+
group_start->next = cur;
269+
if (cur)
270+
cur->prev = group_start;
274271

275-
cur = group_tail->next;
276272
count -= k;
277273
}
278-
return;
279274
}
280275

281276
/* Sort elements of queue in ascending/descending order */
282-
void q_sort(struct list_head *head, bool descend)
277+
static struct list_head *merge(struct list_head *l1,
278+
struct list_head *l2,
279+
bool descend)
283280
{
284-
if (!head || list_empty(head) || head->next == head->prev) {
285-
return;
281+
struct list_head dummy;
282+
struct list_head *tail = &dummy;
283+
284+
while (l1 && l2) {
285+
const element_t *e1 = list_entry(l1, element_t, list);
286+
const element_t *e2 = list_entry(l2, element_t, list);
287+
288+
bool condition = descend ? (strcmp(e1->value, e2->value) < 0)
289+
: (strcmp(e1->value, e2->value) > 0);
290+
291+
if (!condition || strcmp(e1->value, e2->value) == 0) {
292+
tail->next = l1;
293+
l1 = l1->next;
294+
} else {
295+
tail->next = l2;
296+
l2 = l2->next;
297+
}
298+
299+
tail->next->prev = tail;
300+
tail = tail->next;
286301
}
287302

288-
head->prev->next = NULL;
289-
struct list_head *sorted = merge_sort(head->next, descend);
303+
tail->next = l1 ? l1 : l2;
304+
if (tail->next)
305+
tail->next->prev = tail;
290306

291-
LIST_HEAD(tmp);
292-
list_splice_tail_init(sorted, &tmp);
293-
list_splice_tail_init(&tmp, head);
307+
return dummy.next;
294308
}
295-
296309
static struct list_head *merge_sort(struct list_head *head, bool descend)
297310
{
298311
if (!head || !head->next)
299312
return head;
300313

301314
struct list_head *slow = head, *fast = head->next;
302-
303315
while (fast && fast->next) {
304316
slow = slow->next;
305317
fast = fast->next->next;
@@ -314,39 +326,30 @@ static struct list_head *merge_sort(struct list_head *head, bool descend)
314326
return merge(left, right, descend);
315327
}
316328

317-
static struct list_head *merge(struct list_head *l1,
318-
struct list_head *l2,
319-
bool descend)
329+
void q_sort(struct list_head *head, bool descend)
320330
{
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+
if (!head || list_empty(head) || head->next == head)
332+
return;
331333

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-
}
334+
head->prev->next = NULL;
335+
struct list_head *sorted = merge_sort(head->next, descend);
341336

342-
tail = tail->next;
337+
if (!sorted) {
338+
head->next = head;
339+
head->prev = head;
340+
return;
343341
}
344342

345-
tail->next = l1 ? l1 : l2;
346-
if (tail->next)
347-
tail->next->prev = tail;
343+
struct list_head *cur = sorted, *prev = head;
344+
while (cur) {
345+
cur->prev = prev;
346+
prev->next = cur;
347+
prev = cur;
348+
cur = cur->next;
349+
}
348350

349-
return dummy.next;
351+
prev->next = head;
352+
head->prev = prev;
350353
}
351354

352355
/* Remove every node which has a node with a strictly less value anywhere to
@@ -382,25 +385,28 @@ int q_ascend(struct list_head *head)
382385
* the right side of it */
383386
int q_descend(struct list_head *head)
384387
{
385-
if (!head || list_empty(head) || head->next == head->prev) {
388+
if (!head || list_empty(head))
386389
return 0;
387-
}
388390

389-
struct list_head *cur = head->prev, *prev_min = cur, *tmp;
391+
struct list_head *cur = head->prev;
392+
struct list_head *prev = cur->prev;
393+
const element_t *max_elem = list_entry(cur, element_t, list);
390394
int count = 1;
391395

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);
396+
while (prev != head) {
397+
element_t *e = list_entry(prev, element_t, list);
398+
struct list_head *tmp = prev->prev;
395399

396-
if (strcmp(e_cur->value, e_min->value) <= 0) {
397-
prev_min = cur;
398-
count++;
400+
if (strcmp(e->value, max_elem->value) < 0) {
401+
list_del(prev);
402+
free(e->value);
403+
free(e);
399404
} else {
400-
list_del(cur);
401-
free(e_cur->value);
402-
free(e_cur);
405+
max_elem = e;
406+
count++;
403407
}
408+
409+
prev = tmp;
404410
}
405411

406412
return count;

0 commit comments

Comments
 (0)