[Toybox] tsort
Ray Gardner
raygard at gmail.com
Tue Oct 10 15:46:58 PDT 2023
After seeing your comments about tsort in your blog, I thought about trying
to implement Knuth's algorithm, but after I saw how far you'd got with your
version I decided not to for now. I haven't analyzed your version
carefully. It seems to be O(N^2) due to all the work to close up the list
with each item removed, on average? Not sure, but it measures roughly
O(N^2).
I looked at the code and also saw in your blog about the problem of
creating a pointer to an element "below" the keep[] array. Instead of doing
the "usual LP64 trick", had you considered using another array? Something
like this:
--- "..\\1005\\toys\\posix\\tsort.c" 2023-10-05 23:28:19.000000000 -0600
+++ "toys\\posix\\tsort.c" 2023-10-06 10:14:01.448795400 -0600
@@ -43,23 +43,13 @@
static void do_tsort(int fd, char *name)
{
off_t plen = 0;
- char *ss, **pair, *keep[2];
+ char *ss, **pair, *keep[2], *keepfake[2];
long count, // remaining unprocessed pairs
len, // total strings in pair list
out, // most recently added output (counts down from len)
otop, // out at start of this loop over pair[]
otop2, // out at start of previous loop over pair[]
ii, jj, kk;
- unsigned long sigh;
-
- // bsearch()'s first argument is the element to search for,
- // and sbse() compares the second element of each pair, so to find
- // which FIRST element matches a second element, we need to feed bsearch
- // keep-1 but the compiler clutches its pearls about this even when
- // typecast to (void *), so do the usual LP64 trick to MAKE IT SHUT UP.
- // (The search function adds 1 to each argument so we never access
- // memory outside the pair.)
- sigh = ((unsigned long)keep)-sizeof(*keep);
// Count input entries in data block read from fd
if (!(ss = readfd(fd, 0, &plen))) return;
@@ -92,8 +82,12 @@
for (ii = 0; ii<count; ii++) {
// Find pair that depends on itself or no other pair depends on
first str
memcpy(keep, pair+2*ii, sizeof(keep));
- // The compiler won't shut up about keep-1 no matter how we typecast
it.
- if (keep[0]!=keep[1] && bsearch((void *)sigh, pair, count,
sizeof(keep),
+ // bsearch()'s first argument is the element to search for,
+ // and sbse() compares the second element of each pair, so to find
+ // which FIRST element matches a second element, we need to feed
bsearch
+ // an array with a second element == keep[0].
+ keepfake[1] = keep[0];
+ if (keep[0]!=keep[1] && bsearch(keepfake, pair, count, sizeof(keep),
(void *)sbse)) continue;
// Remove from pair list
I think it's clearer, I believe it's a little shorter in code size, and
the run time difference is negligible.
I can post here about how I tested, if you're interested.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20231010/c7e7b615/attachment.htm>
More information about the Toybox
mailing list