I’ve been programming in Python, R and Julia for quite some time now, but I’ve only recently started to learn C. The language is extraordinary. However, since it provides less of a built-in interface, most algorithms are done from scratch. For example, instead of a simple Julia call to sort(my_array)
, in C I would have to program my own sorting algorithm.
For practice, I have been writing algorithms over discrete graphs (e.g. BFS and Greedy coloring). I have found that algorithms that do not require that many loops in high-level languages require a lot of loops in C. Take the following example.
Given a Greedy coloring of a graph with colors r1, ..., rk
, we want to create a new order for the vertices so that all vertices color with rk
are first, those withcolor r(k-1)
are second, and so on. The idea is to run Greedy again in this new order.
Here’s an algorithm that does this (I do not include all the code, but it should be understandable):
u32* reverseOrder(Graph G, u32 nColorsUsed){
printf("Reversing...n");
struct Queue** D = (struct Queue**) calloc(nColorsUsed, sizeof(struct Queue**));
printf("Setting queues...n");
for (u32 i = 0; i < nColorsUsed; i++){
D[i] = createQueue();
}
printf("Enqueing vertices...n");
for (u32 i = 0; i < NumberOfVertices(G); i++){
color c = getColor(i, G);
struct Queue * q = D[c-1];
enQueue(q, i);
}
printf("Setting new order...n");
u32* order = (u32*)calloc(NumberOfVertices(G), sizeof(u32));
u32 j = NumberOfVertices(G) - 1;
for (u32 i = 0; i < nColorsUsed; i++){
struct Queue * q = D[i];
while (q -> front != NULL){
u32 x = pop(q);
order[j] = x;
j--;
}
free(q);
}
printf("Freeing queues...n");
free(D);
return(order);
}
The algorithm has three for
loops and a while
loop. In Python, if somebody showed this to me, I’d be horrified. However, the complexity of the algorithm can be proven to be O(n) with n = number of vertices, which is as good as you can get.
My point is this: it seems that, in C, even algorithms that perform well end up having a lot of loops, which is considered inelegant and suspicious in other languages. I have three questions:
-
Is this truly a characteristic of programming in C, or I’m using a lot of loops simply because I haven’t yet fully understood the language?
-
Is it correct to say all languages use, on average, as many loops as C, but simply hide them under the hood?
-
Assume computational complexity is reasonable; are many loops still frowned upon?