Вам нужна помощь, чтобы понять разницу, верно?
Представьте вызывающую функцию в первом случае:
IntElement *head;
int data;
...
insertInFront (head, data);
Теперь в этом случае адрес, на который указывает head, помещается в стек и передается в качестве аргумента для insertInFront. Когда insertInFront делает head = newElement; изменен только аргумент (в стеке).
Во втором случае вызывающей стороной будет:
IntElement *head;
int data;
...
insertInFront (&head, data);
В этом случае адрес head помещается в стек и передается в качестве аргумента для insertInFront. Когда вы делаете * head = newElement, этот переданный адрес отменяется, чтобы получить адрес исходного заголовка списка, и он изменяется.