Skip to content

Commit 12be675

Browse files
committed
Check if sorting implementation is stable
Introduced node numbering in qtest.c to evaluate q_sort's stability. When encountering two nodes with the same value, the algorithm searches for the address of the node record in the nodes array. It then compares the found node to the current node (cur). If the found node is the same as the current node, it indicates that these two duplicate nodes have not been swapped in position after sorting. However, if the found node is cur->next, it means that the position of the nodes has been swapped. This method avoids altering the structure and instead relies on auxiliary data structures to track node pointersand their original order. However, stability testing is limited to a maximum number of elements, currently set as MAX_NODES, to mitigate potential performance issues. Note: If the dataset is too large, it may lead to excessively long test times, hence the use of MAX_NODES. Testing with the following script to measure the elapsed time for inserting different numbers of nodes: new ih a 10000 sort quit | node count | elapsed time (seconds) | | ---------- | ---------------------- | | 1000 | 0.027906238 | | 10000 | 0.058188249 | | 100000 | 2.445569385 | | 150000 | 5.453358783 | | 200000 | 9.671944194 | | 300000 | 21.581793918 | | 400000 | 40.176436261 | | 500000 | 61.437037665 | The test results reveal a noticeable increase in elapsed time as the number of nodes inserted grows. Specifically, exceeding 100,000 nodes results in significant performance degradation.
1 parent d43e072 commit 12be675

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

qtest.c

+42-1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,23 @@ bool do_sort(int argc, char *argv[])
600600
error_check();
601601

602602
set_noallocate_mode(true);
603+
604+
/* If the number of elements is too large, it may take a long time to check the
605+
* stability of the sort. So, MAX_NODES is used to limit the number of elements
606+
* to check the stability of the sort. */
607+
#define MAX_NODES 100000
608+
struct list_head *nodes[MAX_NODES];
609+
unsigned no = 0;
610+
if (current && current->size && current->size <= MAX_NODES) {
611+
element_t *entry;
612+
list_for_each_entry (entry, current->q, list)
613+
nodes[no++] = &entry->list;
614+
} else if (current && current->size > MAX_NODES)
615+
report(1,
616+
"Warning: Skip checking the stability of the sort because the "
617+
"number of elements %d is too large, exceeds the limit %d.",
618+
current->size, MAX_NODES);
619+
603620
if (current && exception_setup(true))
604621
q_sort(current->q, descend);
605622
exception_cancel();
@@ -624,8 +641,32 @@ bool do_sort(int argc, char *argv[])
624641
ok = false;
625642
break;
626643
}
644+
/* Ensure the stability of the sort */
645+
if (current->size <= MAX_NODES &&
646+
!strcmp(item->value, next_item->value)) {
647+
bool unstable = false;
648+
for (unsigned i = 0; i < MAX_NODES; i++) {
649+
if (nodes[i] == cur_l->next) {
650+
unstable = true;
651+
break;
652+
}
653+
if (nodes[i] == cur_l) {
654+
break;
655+
}
656+
}
657+
if (unstable) {
658+
report(
659+
1,
660+
"ERROR: Not stable sort. The duplicate strings \"%s\" "
661+
"are not in the same order.",
662+
item->value);
663+
ok = false;
664+
break;
665+
}
666+
}
627667
}
628668
}
669+
#undef MAX_NODES
629670

630671
q_show(3);
631672
return ok && !error_check();
@@ -1263,4 +1304,4 @@ int main(int argc, char *argv[])
12631304
ok = finish_cmd() && ok;
12641305

12651306
return !ok;
1266-
}
1307+
}

0 commit comments

Comments
 (0)