You may remember that a pointer stores an address, recursion needs a base case, a stack is LIFO and a queue is FIFO, yet still lose marks when all four appear in one output trace. Programming Concepts and Data Structures and Algorithms are the first two areas of the TPSC Assistant Technical Officer (Computer Science) technical core, and a single output-trace question can put both on the same page. The C program below turns {2, 1, 3, 2} into {8, 6, 5, 2}, then performs exact stack and queue removals. It is a teaching example, not a past TPSC question.
Turn C code into a state table before tracing it
Draw this trace sheet before calculating.
call | p points to | n | action on return | array state | top | front | rear |
|---|---|---|---|---|---|---|---|
before first call |
| 4 | not reached |
| -1 | 0 | -1 |
Start with a = {2, 1, 3, 2} and N = 4. The stack and queue have no logical elements, so top = -1, front = 0 and rear = -1.
An int *p holds an integer address. *p accesses that integer, while p + 1 advances by one int element. With p = &a[1], *(p + 1) = a[2] = 3, whereas *p + 1 = a[1] + 1 = 2 before recursion. Parentheses decide which value is used. The TPSC ATO (CS) exam preparation category collects the Computer Science courses for this route if you want structured practice.
Worked trace: pointers and recursion build suffix sums
Read the whole program once before tracing any line of it:
#include <stdio.h>
#define N 4
void suffix_sum(int *p, int n) {
if (n == 1) {
return;
}
suffix_sum(p + 1, n - 1);
*p += *(p + 1);
}
int main(void) {
int a[N] = {2, 1, 3, 2};
int stack[N], queue[N];
int top = -1, front = 0, rear = -1;
suffix_sum(a, N);
for (int i = 0; i < N; i++) {
stack[++top] = a[i];
queue[++rear] = a[i];
}
printf("array:");
for (int i = 0; i < N; i++) printf(" %d", a[i]);
printf("\nstack pop:");
while (top >= 0) printf(" %d", stack[top--]);
printf("\nqueue delete:");
while (front <= rear) printf(" %d", queue[front++]);
printf("\n");
return 0;
}First trace only the recursive calls. Descent creates (p=&a[0], n=4), (&a[1], 3), (&a[2], 2) and (&a[3], 1). The last call meets n == 1 and returns without changing a[3]. Each suspended frame then resumes at the statement following its recursive call. Since every older frame points one element farther left, the writes travel from a[2] back to a[0].
The assignment sits after the recursive call, so it runs during unwinding, from the right end towards the left. Each frame adds the value to its right, which is already a finished suffix sum, so one pass builds them all. Continue the same sheet, one return at a time:
call | p points to | n | action on return | array state | top | front | rear |
|---|---|---|---|---|---|---|---|
innermost return | a[3] | 1 | base case, no write | {2, 1, 3, 2} | -1 | 0 | -1 |
next return | a[2] | 2 | a[2] = 3 + 2 = 5 | {2, 1, 5, 2} | -1 | 0 | -1 |
next return | a[1] | 3 | a[1] = 1 + 5 = 6 | {2, 6, 5, 2} | -1 | 0 | -1 |
outermost return | a[0] | 4 | a[0] = 2 + 6 = 8 | {8, 6, 5, 2} | -1 | 0 | -1 |
Notice that top, front and rear have not moved yet: main only fills the two structures after suffix_sum returns. The exact output is:
array: 8 6 5 2
stack pop: 2 5 6 8
queue delete: 8 6 5 2![Call stack for suffix_sum from &a[0] down to &a[3], then the unwind writing a[2]=5, a[1]=6 and a[0]=8.](https://cdn.knowledgegate.ai/blog-assets/blog_asset_1784516648656_hneae2.jpg)
Read the same values through stack and queue invariants
The loop inserts the final array values in index order. Prefix increment changes the index before the assignment.
Iteration | value | top after | rear after |
|---|---|---|---|
0 | 8 | 0 | 0 |
1 | 6 | 1 | 1 |
2 | 5 | 2 | 2 |
3 | 2 | 3 | 3 |
The first insertion therefore moves top from -1 to 0 and rear from -1 to 0. After all four iterations, both storage arrays contain [8, 6, 5, 2] at positions 0..3. The stack has top = 3; the queue has front = 0 and rear = 3.
Now apply the indices. Popping reads 3, 2, 1, 0, so the stack prints 2 5 6 8. Queue deletion reads 0, 1, 2, 3, so the queue prints 8 6 5 2. Stored values do not move; only the active boundary index changes. This example is a four-element linear queue without wrap-around. A production circular queue would advance indices modulo capacity and require an explicit empty/full rule. Use Stacks and Queues MCQs: 12 Solved as retrieval practice after tracing.

Extend the trace method to linked lists, trees and complexity
Reuse the same values as a singly linked list: 8 -> 6 -> 5 -> 2 -> NULL. To insert 7 after 6, first set newNode->next to the old 6->next, the node containing 5. Then set 6->next = newNode. The result is 8 -> 6 -> 7 -> 5 -> 2 -> NULL. Reversing those assignments can lose the tail. To delete 5, change the node 7 link from 5 to 2, then release the detached node. The result is 8 -> 6 -> 7 -> 2 -> NULL.
Now put the same four values into a binary search tree, where height decides the cost. Inserting 8, 6, 5, 2 in that order gives the left chain 8 -> 6 -> 5 -> 2: height h = 3 edges, so finding 2 costs four comparisons. Insert the identical set as 5, 2, 6, 8 and you get 5 with children 2 and 6, and 8 below 6: height h = 2, so no search exceeds three comparisons. Same keys, same n, only the insertion order changed. Measure height in edges on the longest root-to-leaf path, and state that convention in your answer.
State assumptions before choosing a complexity:
Operation | Complexity and assumption |
|---|---|
Valid array-index access |
|
Search unsorted array or singly linked list |
|
Stack push/pop, queue enqueue/dequeue |
|
BST search |
|
Binary Trees and Binary Search Trees works through more insertion orders and the traversal questions built on them.
Use an exam-safe output-tracing method
Use five passes on scratch paper. First, mark the base case. Second, record the element targeted by every pointer. Third, keep descent separate from unwind. Fourth, update only one structure index at a time. Fifth, compare final storage with printed order. Treat every arrow as a checkpoint, not a mental shortcut.
For this program, the compressed chain is &a[0]..&a[3] -> base at n=1 -> suffix sums 5, 6, 8 -> a={8,6,5,2} -> top=3, front=0, rear=3 -> stack 2,5,6,8 and queue 8,6,5,2.
Practise every form of the question: predict the output, identify *(p + 1), spot a missing base case, trace top, front or rear, repair a linked-list insertion, compute a BST height from an insertion order, and compare complexity under stated assumptions. The TPSC ATO (CS) Test Series gives you timed sets for the same work under clock pressure.
Compact trap list: cause, wrong result and repair
Trap | What goes wrong | Repair |
|---|---|---|
Read | Wrong operand | Keep parentheses |
Omit or misplace | Wrong stop | Test first |
Update during descent | Wrong sums | Update on unwind |
Use | Not a portable trace | Separate operations |
Start | Skips index | Start at |
Pop at | Empty read | Require |
Delete at | Empty read | Require |
Rewire | Tail lost | Save old |
Call linked-list positional access | Traversal ignored | Use |
Call every BST operation | Height ignored | Use |
The repair habit is simple: write the invariant beside the trace, then verify boundary values before executing the next line.
Short version and one controlled variation
Reconstruct the result from the right. Recursion reaches a[3] = 2; unwinding makes a[2] = 5, a[1] = 6 and a[0] = 8. The stack removes 2 5 6 8, while the queue removes 8 6 5 2. Those same four keys build a BST of height 3 when inserted as 8, 6, 5, 2 and height 2 when inserted as 5, 2, 6, 8. Now change only the input to {4, 0, 2, 1}. Its suffix sums are {7, 3, 3, 1}, its stack output is 1 3 3 7, and its queue output is 7 3 3 1.
For a structured next step, the TPSC ATO (CS) 2026 Complete Course carries the programming and data-structures work with the plan already built. KnowledgeGate's 2,400+ C Programming and Data Structures questions are there when you want more volume to drill.




