First, I have a correction to make to a claim that you made:
In the traversal, whenever the node has a left child a copy of it is made to the right child of its predecessor
A copy of the [current] node is not made to the right child of its [current node's] predecessor - the right child of current node's predecessor is pointed to current node - a pointer does not make any copy; instead it just points to the current node that already exists.
Now to answer your question about your code snippet:
while(pre->right != NULL && pre->right != current)
pre = pre->right;
- That loop does add time to the running of the algorithm [compared to if that loop were not in the code]
- But in a worst case, the time it adds is exactly n (taking the run time from n to 2n). This worst case happens when every single node must be visited an extra time, in order to find all predecessors; by the way, each such extra visit of a given node is the only extra time it is visited when finding predecessors (that's because finding any other predecessor will never travel over the same nodes that were traveled through to find any other predecessor) - that explains why the extra time contributes going from n -> 2n [linear] but not n -> n^2 [quadratic]
- Even though 2n > n, when [Big-O] complexity is considered, O(2n) = O(n)
- In other words, taking longer time of 2n compared to n is not actual extra complexity: n & 2n runtimes both have complexities of identical O(n) [they are both "linear"]
Now even though it may have sounded like I was implying above that the entire algorithm runtime is 2n, it is not - it is actually 3n.
- The loop that is in just the code snippet itself contributes n time
- But the algorithm as a whole runs in 3n because each node is visited at most 3 times {once/first to "thread" it back to the node that it is a predecessor of (the ultimate goal that the code snippet helps achieve); a 2nd time when it is arrived at in otherwise normal traversal [as opposed to anything to do with predecessor threading]; and then a 3rd/final time when it is found as predecessor [that itself for the 2nd/final time] again and its right-child pointer/thread is removed from pointing to right-child of current node [directly before printing current node]}
- And again [just as complexity O(2n) = O(n)], complexity O(3n) = O(n)
- So to summarize: Yes, your code snippet loop does contribute time, but NOT extra time complexity
By the way, I don't think this line (from the full algorithm) to remove the old predecessor "thread" reference is strictly necessary (although it doesn't hurt, and can be considered nice tidying-up):
pre->right = NULL;