TPSC Computer Science: C Programming and Data Structures Worked Playbook

Trace one complete C program from recursive pointer calls to exact stack and queue output, then extend the same state-table method to linked lists, trees and complexity.

KnowledgeGate Team

Exam prep & CS education

Updated 29 Jul 20267 min read

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

a[0]

4

not reached

{2, 1, 3, 2}

-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.

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 ++top

rear after ++rear

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.

Stack and queue both holding 8, 6, 5, 2, with the stack printing 2 5 6 8 and the queue printing 8 6 5 2.

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

O(1)

Search unsorted array or singly linked list

O(n)

Stack push/pop, queue enqueue/dequeue

O(1) when implementation and capacity assumptions hold

BST search

O(h), so O(log n) only with logarithmic height and O(n) when skewed

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 *p + 1 as *(p + 1)

Wrong operand

Keep parentheses

Omit or misplace n == 1

Wrong stop

Test first

Update during descent

Wrong sums

Update on unwind

Use a[i] = i++

Not a portable trace

Separate operations

Start top or rear at 0 with prefix ++

Skips index 0

Start at -1

Pop at top == -1

Empty read

Require top >= 0

Delete at front > rear

Empty read

Require front <= rear

Rewire 6->next before saving node 5

Tail lost

Save old next first

Call linked-list positional access O(1)

Traversal ignored

Use O(n)

Call every BST operation O(log n)

Height ignored

Use O(h) and state balance

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.