Although tail recursion optimization is not required by C, if you can convert it to tail recursion (and you can do a lot of work here), then when this optimization is applied, you can maintain readability, clarity and brevity of recursion with the same performance (time and space) as the best non-recursive solution.
I changed the conditions of the function a bit so that it could work in an empty list without nodes (where p is null) and in this case it returns null. This tail is recursive and requires a different parameter:
ListNode* findLargestRecurse(ListNode* p, ListNode* largest) { // this is an implementation detail, and would not be called directly // requires that largest is not null, but p may be null if (!p) return largest; if (p->item > largest->item) largest = p; return findLargestRecurse(p->next, largest); } // preconditions: list head pointer is passed as a parameter, and may be null // postcondition: returns the node with the largest value, or null ListNode* findLargest(ListNode* p) { if (!p) return 0; // mark A, see below return findLargestRecurse(p->next, p); }
Note that you are using the master record, findLargest, to set up the initial conditions / context for the actual recursion, findLargestRecurse.
However, I would write this tail recursion as an iterative while loop to rely less on what is currently both very specific to the compiler and generally unfamiliar in C, which is easy to do:
// preconditions: list head pointer is passed as a parameter, and may be null // postcondition: returns the node with the largest value, or null ListNode* findLargest(ListNode* p) { ListNode* largest = 0; for (; p; p = p->next) { if (!largest || p->item > largest->item) { largest = p; } } return largest; }
You can isolate the !largest condition from the loop by doing this beforehand, checking the base case in the same way as the first findLargest ("mark A").
And looking at it now, you may wonder why I called the recursive version shorter: it really is not for this trivial example. This is partly due to the fact that C is intended to be iterated (pay attention to the for loop in particular), somewhat because I tried to be detailed in recursion rather than dumping it as usual (so you could understand this more easily), but the rest because it is a simple problem.