Pointers and memory layout
A pointer holds an address. Dereferencing accesses the value at that address. Pointer arithmetic on an array of type T advances by sizeof(T) bytes per unit. A null pointer dereference is undefined behavior. Pass-by-pointer lets a function modify the caller's variable.
Check yourself: What does the pointer point to after the assignment, and is it still valid?
Recursion and the call stack
Each recursive call creates a new stack frame with its own local variables. Identify the base case, the recursive reduction, and what each call returns. The total number of frames determines stack depth. Tail recursion reuses frames only when the compiler optimizes it.
Check yourself: Does every recursive path eventually reach the base case?
Linked lists, stacks, and queues
A singly linked list supports O(1) insertion at the head but O(n) search. A stack is last-in-first-out; a queue is first-in-first-out. Both can be implemented with arrays or linked nodes. Array-based versions may need resizing; linked versions use extra pointer storage.
Check yourself: Are you updating both the pointer and the node it references?
Trees and binary search trees
In a binary search tree, left descendants have smaller keys and right descendants have larger keys. Search, insert, and delete are O(h) where h is the height. A balanced BST maintains h = O(log n); an unbalanced one can degrade to O(n). Inorder traversal of a BST yields sorted order.
Check yourself: Does the BST property hold at every node after your operation?
Hashing
A hash table maps keys to slots via a hash function. Collisions are unavoidable when the key space exceeds the table size. Chaining uses linked lists per slot; open addressing probes for the next available slot. Average-case O(1) lookup depends on a good hash function and a reasonable load factor.
Check yourself: What happens when two different keys hash to the same slot?