The assignment says you need to store student records, find a student by ID, display students by score, and undo the most recent update. You have learned arrays, linked lists, stacks, queues, sets, maps, trees, graphs, and heaps. Which one are you supposed to use?
Possibly more than one.
Choosing a data structure is a design decision, not a memory test where every problem has one secret vocabulary word. Start with the operations the program must perform, the information it must preserve, the constraints in the brief, and the techniques the instructor expects you to practice. Then compare the simplest permitted designs that satisfy those needs.
Use this sequence:
- Translate the brief into data and operations.
- Mark rules about order, uniqueness, priority, and relationships.
- Record required or prohibited techniques.
- Identify which operations happen frequently or carry a performance requirement.
- Sketch two realistic designs.
- Test both designs on a tiny example.
- Choose the design you can implement, test, and justify.
Choose from the assignment, not from whichever data structure was covered most recently in class.
Begin with nouns, verbs, and constraints
Read the brief once for the overall problem. Read it again with three labels.
Nouns: what information exists?
Examples:
- Students
- Course codes
- Support tickets
- Cities
- Roads
- Products
- Transactions
- Words
- Files
These nouns suggest records or entities, but they do not choose a data structure by themselves.
Verbs: what must happen to the information?
Examples:
- Add a student
- Find a student by ID
- Remove the most recent action
- Process requests in arrival order
- Find the highest-priority task
- List records alphabetically
- Detect duplicates
- Find a path between two cities
The verbs are usually more useful than the nouns. “Store students” is vague. “Find a student repeatedly by unique ID” points toward key-based lookup, and “Undo the most recent change” describes last-in, first-out behavior.
Constraints: what limits the solution?
Look for:
- Required algorithm or data structure
- Prohibited built-in functions or libraries
- Maximum input size
- Time or memory limits
- Required output order
- Duplicate-handling rules
- Tie-breaking rules
- Recursion requirements or restrictions
- Language version
- Expected complexity for an operation
- A rubric item asking for design justification
Constraints can overturn the most convenient implementation. A Python dictionary might be a sensible production choice for lookup, but it is not an acceptable replacement when the learning objective is to implement a binary search tree. In another assignment, building a tree from scratch may be unnecessary risk because the task is about file parsing and a built-in map is explicitly permitted.
Separate behavior from implementation
Students often mix up an abstract data type with one particular implementation.
A stack describes last-in, first-out behavior and can be implemented using an array, dynamic array, or linked structure. A queue describes first-in, first-out behavior. A map associates keys with values, but a map may be implemented with hashing, a search tree, or another structure.
University data-structure courses deliberately assess this distinction. Stanford’s CS106B, for example, teaches vectors, stacks, queues, sets, maps, and priority queues, and its practice exams ask students to pick the right collection for a design, such as a map from student ID to a stack of submissions. Some assignments require students to implement the same abstract type using different internal representations so they can compare operations and complexity.
That means your decision may have two levels:
- Which behavior does the program need?
- Which permitted implementation best provides that behavior?
Do not jump to level two before answering level one.
A practical guide to the main choices
The table below is a starting point. It does not override the assignment or guarantee that one option is always best.
| Need in the assignment | Likely candidate | Question you still need to answer |
|---|---|---|
| Keep items in a sequence | Array or list | Is the size fixed? Do you need frequent insertion in the middle? |
| Access an item by position | Array or list | Is positional access actually part of the task? |
| Associate a unique key with a value | Map or dictionary | Must the keys remain sorted or preserve another order? |
| Prevent duplicate values | Set | Do you also need occurrence counts or original order? |
| Process the earliest item first | Queue | How are canceled or delayed items handled? |
| Process the newest item first | Stack | Is undo truly last-in, first-out? |
| Repeatedly choose the most urgent item | Priority queue (often implemented as a heap) | How are equal priorities resolved? |
| Represent parent-child relationships | Tree | What operations must the hierarchy support? |
| Represent arbitrary connections | Graph | Are edges directed, weighted, or allowed to form cycles? |
| Preserve a fixed grid | Two-dimensional array or grid abstraction | Are coordinates dense, sparse, or bounded? |
The “question you still need to answer” column is where real design happens. Suppose the brief says, “Store unique usernames and display them in the order they registered.” A set handles uniqueness, but a set alone may not express the required registration order in a portable or assignment-approved way. You may need an ordered structure plus a membership structure, or a map whose ordering guarantee matches the language and course constraints.
One assignment can need several structures
There is no prize for forcing the whole program into one container. Imagine a campus tutoring-request system. Each request has:
- A unique request ID
- Student ID
- Subject
- Urgency from 1 (most urgent) to 5 (least urgent)
- Submission time
- Status
The system must:
- Find a request by ID
- Reject duplicate request IDs
- Select the most urgent waiting request
- Break urgency ties by submission time (earlier first)
- Display completed requests in completion order
Now map each requirement to an operation.
| Requirement | Operation | Candidate |
|---|---|---|
| Find request by ID | Repeated key lookup | Map keyed by request ID |
| Reject duplicate ID | Membership check | The same map’s keys |
| Select most urgent request | Repeated priority removal | Priority queue |
| Resolve equal urgency | Secondary comparison by submission time | Priority-queue ordering rule |
| Display completed work in completion order | Append and later iterate | List |
Each structure owns a clear responsibility, so none of this is needless complexity.
But the design raises a new question: when a request changes status, how do the structures stay consistent? If an entry remains in the priority queue after cancellation, the program may select stale work. You might need lazy deletion (check an item’s status when it reaches the front and skip it if it was canceled) or an indexed priority structure that supports removal, depending on the course level and permitted tools. A good design has to be fast on paper and still preserve a coherent state.
A second worked example: submission history with undo
Consider an assignment platform with these operations:
submit(student, assignment, code)saves a new version.undo(student, assignment)discards the latest version and restores the previous one.current(student, assignment)returns the latest remaining version.count(assignment)returns the number of students who currently have a submission.
The word undo suggests a stack because the most recent version should be removed first. But you also need to locate the correct student and assignment.
One possible design is:
assignment number
-> map of student ID to stack of submissions
In Python-like notation (this annotation style needs Python 3.9 or later):
submissions: dict[int, dict[str, list[str]]]
Here the innermost list is used as a stack. The design supports several operations naturally:
- Locate an assignment by number.
- Locate a student by ID.
- Append a new code version.
- Remove the most recent version.
- Remove a student’s map entry when no versions remain.
- Count current submitters as the number of student entries for that assignment, since empty entries are removed.
Could you use one giant list of submission records? Yes. It may be simpler to construct, but repeated lookup, undo, and counting would require more scanning and careful filtering. Whether that tradeoff is acceptable depends on the input size, performance requirements, and learning objective.
The nested design is not universally correct, but it follows from the operations.
Choose the algorithm after you know the state
Data structures describe how information is represented. Algorithms describe how the program transforms or explores it. The two decisions affect each other.
Searching
Ask:
- Is the data already sorted?
- Must it stay sorted after updates?
- Is this one search or thousands of searches?
- Is lookup by position, exact key, range, prefix, or condition?
- Are you required to implement the search?
Binary search is not a magical “fast search”: it requires an ordered search space and a way to access the middle appropriately. If maintaining that order costs more than the searches save, or the assignment forbids sorting first, it may not fit.
Sorting
Define:
- The primary sort key
- Ascending or descending order
- Tie-breaking behavior
- Whether the original order must be preserved for equal keys
- Whether you may use the language’s built-in sort
- Whether the assignment assesses a specific sorting algorithm
“Sort students” is incomplete. “Sort by descending final score, breaking ties by ascending student ID” is implementable and testable.
Traversing trees and graphs
Ask what result is required:
- Any path
- The fewest-edge path
- The least-cost path
- Every reachable node
- Cycle detection
- Dependency order
- Connected components
Breadth-first, depth-first, and cost-aware algorithms solve different problems. Choose from the required result and edge properties, not because one has a familiar name.
Reusing repeated subproblems
Recursion may express the problem clearly but repeat the same state. Memoization or dynamic programming can help when you can define the subproblem state and reuse its result. Do not add a cache until you know what uniquely identifies a subproblem and whether the assignment permits the technique.
Complexity matters, but it is not the only requirement
Students sometimes choose a data structure by repeating a complexity value from a table. That can go wrong in three ways.
First, complexity belongs to an operation and implementation, not to a data-structure name in isolation. A map implemented with hashing and a map implemented with a balanced tree do not have identical behavior or guarantees.
Second, the operation you optimize may not be the one the assignment performs most often. A design that improves rare lookup but complicates every update can be a poor fit.
Third, correctness includes semantics. A structure that removes duplicates is not correct when duplicate events carry meaning. A structure that does not preserve the required order is not rescued by a better complexity label.
Try a small operation budget:
| Operation | How often does it occur? | Required bound, if stated | Candidate A | Candidate B |
|---|---|---|---|---|
| Add item | Once per input record | Not stated | Direct append | Ordered insertion |
| Find by ID | Repeatedly | “Efficient lookup” | Scan list | Keyed map |
| Produce sorted report | Once at end | Not stated | Sort list at end | Maintain sorted structure |
This table forces you to connect the design to the actual workload. If the report is produced once, maintaining sorted order after every update may be unnecessary. If the course requires a sorted tree, the pedagogical constraint changes the decision.
Language-specific names can hide the same idea
Python
Python’s core structures include lists, sets, and dictionaries. A list can be used as a stack. For queue-heavy work, a course may recommend a queue-specific type rather than repeatedly removing from the front of a list. Check the permitted standard-library tools.
Java
Java separates collection interfaces such as List, Set, Queue, Deque, and Map from implementations such as ArrayList, HashSet, ArrayDeque, HashMap, and tree-based alternatives. Choose the interface behavior first, then the implementation required by the assignment.
C++
C++ standard containers include sequence containers, ordered and unordered associative containers, and adapters such as stacks, queues, and priority queues. Watch iterator rules, ownership, copying, and whether the course expects you to implement the structure instead of using the standard one.
JavaScript
Arrays are often used for several behaviors, while Map and Set express keyed lookup and uniqueness more directly. An object used as a map has language-specific key and prototype considerations. Follow the course’s target runtime and conventions.
R
Vectors, lists, matrices, data frames, and environments serve different analytical roles. An R assignment may care more about column types, missing values, grouping, and reproducibility than about implementing a low-level structure.
The title “list” does not guarantee identical performance or semantics across languages. Use the documentation for the version and implementation your course expects.
Test the design before writing the full program
Take a tiny input and draw the state after each operation.
For the tutoring-request system, try:
- Request R1 arrives with urgency 3.
- Request R2 arrives with urgency 1.
- Request R3 arrives with urgency 1 but later than R2.
- R2 is canceled.
- Staff asks for the next request.
- The system looks up R1 by ID.
Can your design answer each operation without losing order or selecting a canceled request? What exactly happens on equal priority? What does the map contain after completion?
Also test:
- Empty data
- One item
- Duplicate key
- Duplicate value
- Equal priority
- Missing key
- Reversed input order
- Boundary values
- Largest input described in the brief
If the state diagram becomes contradictory, fix the design before building classes around it.
Compare two candidates honestly
When you are torn between designs, use the same questions for both.
| Decision question | Candidate A | Candidate B |
|---|---|---|
| Does it preserve the required information? | ||
| Does it express the required order? | ||
| How are duplicates and ties handled? | ||
| Which frequent operations are direct? | ||
| Which operations require scanning or conversion? | ||
| Is it permitted by the assignment? | ||
| Can I implement and test it reliably? | ||
| Can I explain it against an alternative? |
The implementation-risk row does not excuse you from performance requirements. A theoretically attractive design that you cannot implement correctly before the deadline is not automatically better than a simpler permitted design that satisfies the stated constraints.
Common mistakes when choosing a structure
Choosing the most advanced topic you know
A tree is not inherently better than a list: it solves different operational needs at a higher implementation cost.
Choosing one structure for everything
Lookup, priority, history, and presentation order may deserve separate representations. If you use multiple structures, define how updates keep them consistent.
Ignoring ties
Priority alone does not establish a complete order when two items have equal priority. Use the brief’s tie rule or ask for one.
Treating a set as a list with faster lookup
A set changes the meaning of duplicates and may not provide the ordering your output needs.
Assuming built-ins are always acceptable
Many assignments assess the implementation itself. A library call can bypass the required learning objective even when the output is correct.
Implementing everything from scratch
The opposite mistake is rebuilding maps, queues, or sorts when the assignment permits and expects standard collections. That adds defect risk without serving the task.
Optimizing before the contract is stable
If you have not settled duplicate behavior, ordering, error cases, and required operations, a performance discussion is premature.
Copying an AI-suggested design without tracing it
An AI tool may suggest a graph, heap, or nested map that sounds plausible but does not match the rubric or course level. If course policy permits AI use, require the suggestion to state its assumptions and compare it with the written constraints. Then draw the state and test it yourself.
How to explain the choice in a report or code defense
Structure it in four parts:
- Requirement: What behavior or constraint matters?
- Choice: What structure or algorithm did you select?
- Alternative: What realistic option did you consider?
- Tradeoff: Why does your choice fit this assignment better?
Weak explanation:
I used a dictionary because it is faster.
Stronger explanation:
The program repeatedly retrieves a request by unique ID, so I store requests in a dictionary keyed by that ID. A list would preserve a display order, but each exact-ID lookup would require searching the records. I keep completion order separately in a list because the report requires that sequence.
The stronger answer defines the operation, acknowledges an alternative, and explains why one structure is not being forced to serve every requirement.
MyCodingPal’s guide to explaining and defending a programming assignment offers a fuller preparation method for tracing execution, justifying decisions, discussing tests, and handling live changes.
What to ask when you are stuck between two options
Do not ask, “Which data structure should I use?” without context.
Prepare:
- The exact requirement
- Required and prohibited techniques
- Important operations
- Ordering and duplicate rules
- Expected input size
- The two candidates
- One tiny state example
- Your current tradeoff analysis
Then ask something like:
“The program needs repeated lookup by student ID and one final report sorted by score. The rubric permits built-in collections. I am considering a dictionary for lookup and sorting a list of its values once for the report. Is there a requirement that would make maintaining a sorted structure throughout the program necessary?”
That question shows work. It also lets a tutor or teaching assistant correct the decision without replacing your design process.
If your course permits tutoring, MyCodingPal offers one-on-one tutoring, debugging and code review. Its do my programming homework page explains the available support options. The final structure should still be one you can implement and defend yourself.
Final decision worksheet
Before coding, fill in these statements:
The program stores:
The most important operations are:
The required ordering is:
Duplicates are:
Ties are resolved by:
The instructor requires:
The instructor prohibits:
The largest or most difficult input is:
Candidate A is:
It fits because:
Its main drawback is:
Candidate B is:
It fits because:
Its main drawback is:
I chose:
I will verify it using:
Pick the design whose behavior matches the assignment, whose costs fit the stated constraints, and whose reasoning survives a test case and a follow-up question. It does not have to be the most sophisticated one.
Frequently asked questions
Should I always choose the fastest data structure?
No. It must first be correct, permitted, and compatible with required ordering, duplicates, and operations. Performance matters when the brief, input, or rubric makes it relevant.
Can an assignment use more than one data structure?
Yes. Many useful designs combine structures, such as a map for lookup and a list for report order. Define how updates keep the representations consistent.
What if the assignment requires a specific structure?
Use it unless the instructions provide an alternative. The learning objective may be implementing or analyzing that structure rather than choosing the most convenient library tool.
How do I choose between a list and a set?
Ask whether duplicates carry meaning, whether order matters, and which operations are required. A set expresses uniqueness; a list expresses a sequence. Neither is universally better.
How do I choose between a queue and a priority queue?
Use a queue when processing order follows arrival. Use a priority queue when another priority determines removal order. Define how ties are handled.
Do I need Big-O analysis in every assignment?
Only when the course or design decision calls for it. Even without a formal proof, identify which operations repeat and whether the input can grow enough for the choice to matter.
Can I ask an AI tool which structure to use?
Only if course policy permits it. Supply the constraints, ask for alternatives and tradeoffs rather than a finished solution, and verify the recommendation against the brief. You remain responsible for the submitted design.