Task: Tarjan

C: #include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>

#ifndef min
#define min(x, y) ((x)<(y) ? (x) : (y))
#endif

struct edge {
	void *from;
	void *to;
};

struct components {
	int nnodes;
	void **nodes;
	struct components *next;
};

struct node {
	int index;
	int lowlink;
	bool onStack;
	void *data;
};

struct tjstate {
	int index;
	int sp;
	int nedges;
	struct edge *edges;
	struct node **stack;
	struct components *head;
	struct components *tail;
};

static int nodecmp(const void *l, const void *r)
{
	return (ptrdiff_t)l -(ptrdiff_t)((struct node *)r)->data;
}

static int strongconnect(struct node *v, struct tjstate *tj)
{
	struct node *w;

	
	v->index = tj->index;
	v->lowlink = tj->index;
	tj->index++;
	tj->stack[tj->sp] = v;
	tj->sp++;
	v->onStack = true;

	for (int i = 0; i<tj->nedges; i++) {
		
		if (tj->edges[i].from != v) {
			continue;
		}
		w = tj->edges[i].to;
		
		if (w->index == -1) {
			int r = strongconnect(w, tj);
			if (r != 0)
				return r;
			v->lowlink = min(v->lowlink, w->lowlink);
		
		} else if (w->onStack) {
			v->lowlink = min(v->lowlink, w->index);
		}
	}

	
	if (v->lowlink == v->index) {
		struct components *ng = malloc(sizeof(struct components));
		if (ng == NULL) {
			return 2;
		}
		if (tj->tail == NULL) {
			tj->head = ng;
		} else {
			tj->tail->next = ng;
		}
		tj->tail = ng;
		ng->next = NULL;
		ng->nnodes = 0;
		do {
			tj->sp--;
			w = tj->stack[tj->sp];
			w->onStack = false;
			ng->nnodes++;
		} while (w != v);
		ng->nodes = malloc(ng->nnodes*sizeof(void *));
		if (ng == NULL) {
			return 2;
		}
		for (int i = 0; i<ng->nnodes; i++) {
			ng->nodes[i] = tj->stack[tj->sp+i]->data;
		}
	}
	return 0;
}

static int ptrcmp(const void *l, const void *r)
{
	return (ptrdiff_t)((struct node *)l)->data
		- (ptrdiff_t)((struct node *)r)->data;
}


struct components *tarjans(
		int nnodes, void *nodedata[],
		int nedges, struct edge *edgedata[],
		int *error)
{
	struct node nodes[nnodes];
	struct edge edges[nedges];
	struct node *stack[nnodes];
	struct node *from, *to;
	struct tjstate tj = {0, 0, nedges, edges, stack, NULL, .tail=NULL};

	
	for (int i = 0; i<nnodes; i++) {
		nodes[i] = (struct node){-1, -1, false, nodedata[i]};
	}
	qsort(nodes, nnodes, sizeof(struct node), ptrcmp);

	
	for (int i = 0; i<nedges; i++) {
		from = bsearch(edgedata[i]->from, nodes, nnodes,
			sizeof(struct node), nodecmp);
		if (from == NULL) {
			*error = 1;
			return NULL;
		}
		to = bsearch(edgedata[i]->to, nodes, nnodes,
			sizeof(struct node), nodecmp);
		if (to == NULL) {
			*error = 1;
			return NULL;
		}
		edges[i] = (struct edge){.from=from, .to=to};
	}

	
	for (int i = 0; i < nnodes; i++) {
		if (nodes[i].index == -1) {
			*error = strongconnect(&nodes[i], &tj);
			if (*error != 0)
				return NULL;
		}
	}
	return tj.head;
}




Go: package main

import (
    "fmt"
    "math/big"
)


var g = [][]int{
    0: {1},
    2: {0},
    5: {2, 6},
    6: {5},
    1: {2},
    3: {1, 2, 4},
    4: {5, 3},
    7: {4, 7, 6},
}

func main() {
    tarjan(g, func(c []int) { fmt.Println(c) })
}



func tarjan(g [][]int, emit func([]int)) {
    var indexed, stacked big.Int
    index := make([]int, len(g))
    lowlink := make([]int, len(g))
    x := 0
    var S []int
    var sc func(int) bool
    sc = func(n int) bool {
        index[n] = x
        indexed.SetBit(&indexed, n, 1)
        lowlink[n] = x
        x++
        S = append(S, n)
        stacked.SetBit(&stacked, n, 1)
        for _, nb := range g[n] {
            if indexed.Bit(nb) == 0 {
                if !sc(nb) {
                    return false
                }
                if lowlink[nb] < lowlink[n] {
                    lowlink[n] = lowlink[nb]
                }
            } else if stacked.Bit(nb) == 1 {
                if index[nb] < lowlink[n] {
                    lowlink[n] = index[nb]
                }
            }
        }
        if lowlink[n] == index[n] {
            var c []int
            for {
                last := len(S) - 1
                w := S[last]
                S = S[:last]
                stacked.SetBit(&stacked, w, 0)
                c = append(c, w)
                if w == n {
                    emit(c)
                    break
                }
            }
        }
        return true
    }
    for n := range g {
        if indexed.Bit(n) == 0 && !sc(n) {
            return
        }
    }
}