MGU Computer Science Series — CS Foundations
Part III: Data and Algorithms
Lists · Arrays · Strings · Records · Dictionaries · Stacks · Queues
Chapter 11 of 28
MGU Computer Science Series  ·  Computer Science Foundations  ·  Library Textbook Edition

Chapter 11:
Data Structures
at an Introductory Level

How programs organize information — lists, arrays, strings, records, dictionaries, stacks, and queues — and how to choose the right structure for the problem at hand

■ CS Level: Foundations ■

■ 10 Sections  •  Part III · Chapter 11 of 28 ■

Follows Part II: Programming Foundations  ·  Prepares students for Chapter 12: Searching, Sorting, and Efficiency

Purpose and Overview

Every program works with data. A music app tracks thousands of songs. A school system stores tens of thousands of student records. A navigation app holds the coordinates of millions of roads. In each case, the program does not just store data — it organizes data so that the right piece can be found, updated, added, or removed quickly and reliably. The way a program organizes its data is called a data structure.

Part II of this textbook introduced you to variables that hold a single value — a number, a string, a Boolean. But most real programs deal with collections of values. A playlist is a collection of song titles. A gradebook is a collection of scores. A contact list is a collection of name-and-phone-number pairs. Each kind of collection calls for a different organizational strategy, and choosing the right strategy is one of the central skills of computer science.

This chapter introduces the most important data structures you will encounter as a beginning computer scientist: lists and arrays, strings as sequences, records, dictionaries and maps, stacks, and queues. The goal is not to make you an expert programmer of every structure — that depth belongs in Data Structures and Algorithms. The goal is to give you a clear mental model of each structure, a sense of what problems it solves, and enough familiarity to read, trace, and reason about code that uses them.

Opening Question

A teacher needs to store the names of every student in a class, then add a new student who enrolled late, then find and remove a student who transferred out. Which way of organizing the names would make each of these tasks easiest? A plain numbered list? A sorted alphabetical list? A special collection that supports fast search? By the end of this chapter you will know how to think through exactly these kinds of decisions — and why the structure you choose shapes every operation that follows.

10Sections
10Objectives
18Key Terms
8+Worked Examples

Learning Objectives

  1. 1Explain why programs need data structures beyond single-value variables.
  2. 2Describe the structure of a list and access elements using zero-based indexes.
  3. 3Explain what an array is and how it differs from a general list.
  4. 4Treat a string as a sequence of characters and apply indexing and slicing to it.
  5. 5Describe a record as a named collection of fields and explain how records model real-world entities.
  6. 6Explain how a dictionary maps keys to values and describe operations on it.
  7. 7Describe the stack data structure and explain the Last-In, First-Out principle.
  8. 8Describe the queue data structure and explain the First-In, First-Out principle.
  9. 9Choose an appropriate data structure given a description of the problem and the operations required.
  10. 10Identify data structures used in real software systems and explain why they were chosen.

Sections at a Glance

Sections 11.1 – 11.4
Lists, Indexes, and Arrays — The Foundation of Ordered Collections
Why Structure Matters · Lists and Sequences · Indexes · Arrays

Why Data Structures Matter

Imagine you need to store the names of all 300 students at a school. You could create 300 separate variables — student1, student2, and so on all the way to student300. But this quickly becomes unmanageable. What if you need to find a student's name? You would have to check all 300 variables one by one. What if you need to add a student? You have to invent a new variable. What if you need to sort the names alphabetically? You would be facing hundreds of separate operations with no clear way to loop through them.

The problem is not the data itself — it is the organization. A data structure is a way of arranging and storing data in a computer's memory so that it can be used efficiently. The right data structure makes certain operations fast and easy; the wrong one makes the same operations slow and error-prone. Choosing a data structure is one of the most consequential decisions a programmer makes.

Data structures matter for several practical reasons. First, they determine which operations are natural. A list makes it easy to go through items one by one in order. A dictionary makes it easy to look up a value by name. A stack makes it easy to undo the last action. Second, data structures determine efficiency. Some structures find items quickly; others find them slowly. Some add items quickly; others require rearranging everything. As programs grow large — handling millions of records, responding in milliseconds — the choice of structure becomes critical. Third, data structures shape code. Programs built around well-chosen structures are readable, maintainable, and easier to debug. Programs built around poorly chosen structures become tangled.

Core Idea

A data structure is an organized way to store and access a collection of data. The right structure for a problem depends on what operations the program needs to perform on the data — not just how much data there is.

Connection to Earlier Chapters

In Chapter 7 you learned about variables — containers that hold a single value. In Chapter 9 you used lists briefly to pass collections of items around in functions. This chapter gives those ideas a proper foundation. Every data structure is ultimately a way to extend the single-variable idea to collections of values.

Practice 11.1Concept Check
  1. In your own words, explain what a data structure is and why programs need them.
  2. A program stores the current temperature for each of the 50 US states. What problems would arise if the programmer used 50 separate variables instead of a single collection?
  3. Name two things about a problem that should influence which data structure you choose.
  4. Think of one real-world system you use every day (a streaming app, a school website, a navigation app). What kinds of collections of data does that system probably store?

Lists and Sequences

The most fundamental data structure for an ordered collection is a list. A list is a sequence of items arranged in a specific order. The order matters: the first item is distinct from the second, which is distinct from the third, and so on. Items in a list are also called elements.

A list can hold any kind of item: numbers, strings, Boolean values, or even other lists. In Python, a list is written using square brackets, with items separated by commas.

Example 11.2.1
Creating lists in Python
  • Code scores = [88, 95, 71, 100, 83] names = ["Alice", "Bob", "Carmen", "David"] mixed = [42, "hello", True, 3.14] empty = []
  • Explainscores holds five integers. names holds four strings. mixed holds items of different types. empty is a valid list with no items.

Common List Operations

Once you have a list, there are several standard operations you need to perform on it. The table below shows the most common ones, using Python syntax as a concrete example. The key insight is that these operations — accessing an item, adding an item, removing an item, finding the length — are fundamental to what lists are for, regardless of the programming language.

OperationPython ExampleWhat It Does
Access by positionnames[0]Returns the first element: "Alice"
Find the lengthlen(names)Returns the number of elements: 4
Add to the endnames.append("Eva")Adds "Eva" as the last element
Insert at a positionnames.insert(1, "Bea")Inserts "Bea" at position 1, shifting others
Remove by valuenames.remove("Bob")Removes the first occurrence of "Bob"
Remove by positionnames.pop(2)Removes and returns the item at position 2
Check membership"Alice" in namesReturns True if "Alice" is in the list
Loop through itemsfor name in names:Visits each element in order
Mutability

Python lists are mutable — you can change their contents after they are created. You can add items, remove items, and replace items. This is different from strings, which are immutable (you cannot change individual characters in place). Mutability matters because it affects what your program can do with data after creating it.

Diagram — A List as a Row of Labeled Slots

The list scores = [88, 95, 71, 100, 83] can be visualized as a row of slots. Each slot has an index number (its position) and a value (its content).

Index
0
1
2
3
4
Value
88
95
71
100
83

Highlighted: scores[3] → 100. Counting starts at 0, so position 3 is the fourth slot.

Practice 11.2Lists and Sequences
  1. Write a Python list called days that holds the names of the seven days of the week in order.
  2. Given temps = [72, 68, 75, 80, 77], what does len(temps) return?
  3. A list called items holds ["pen", "paper", "stapler"]. Write the Python statement that adds "tape" to the end of the list.
  4. After the addition above, what does len(items) return?
  5. Can a Python list hold items of different types? Give an example.
  6. Explain the difference between remove("Bob") and pop(2) on a list.

Indexes

The index of an element is its position within the list. Computer science counts positions starting at zero, not one. This is called zero-based indexing, and it is a convention used across virtually all modern programming languages. If a list has five elements, their indexes are 0, 1, 2, 3, and 4. There is no index 5.

Zero-based indexing exists for a mathematical reason rooted in how memory addresses are calculated, but for now the rule is simply: the first element is at index 0, the second at index 1, and so on. The last element is at index (length − 1).

Example 11.3.1
Reading and writing by index
  • Setupcolors = ["red", "green", "blue", "yellow"]
  • Read colors[0] → "red" colors[2] → "blue" colors[3] → "yellow"
  • Write colors[1] = "lime" # Now: ["red", "lime", "blue", "yellow"]
  • Lengthlen(colors) → 4
Indexes run from 0 to len(list) − 1. Assignment by index replaces the existing element.

Index Errors

If you ask for an index that does not exist, the program raises an index error — a runtime error that stops execution. For a list of five elements (indexes 0–4), requesting index 5 or index -6 will cause an error. Always be aware of the valid range of indexes before accessing a list.

Off-By-One Errors

One of the most common mistakes with lists is the off-by-one error — accessing index (length) instead of (length − 1). If scores has 5 elements, valid indexes are 0–4. Writing scores[5] causes an IndexError at runtime. Always double-check that your index does not exceed (length − 1).

Negative Indexing

Python allows negative indexes as a shorthand for counting from the end. Index -1 refers to the last element, -2 to the second-to-last, and so on. This is a convenience feature: colors[-1] is the same as colors[len(colors) - 1].

Diagram — Positive and Negative Indexes
Positive
0
1
2
3
Value
"red"
"green"
"blue"
"yellow"
Negative
-4
-3
-2
-1

Each element has two valid indexes: a positive one counting from the left, and a negative one counting from the right.

Slicing at an Introductory Level

A slice extracts a contiguous portion of a list and returns it as a new list. In Python, the syntax is list[start:stop], where start is the index of the first element to include and stop is the index of the first element to exclude. Slicing never modifies the original list.

Example 11.3.2
Slicing a list
  • Setupnums = [10, 20, 30, 40, 50, 60]
  • Slices nums[1:4] → [20, 30, 40] # indexes 1, 2, 3 nums[0:3] → [10, 20, 30] # indexes 0, 1, 2 nums[3:] → [40, 50, 60] # from index 3 to end nums[:2] → [10, 20] # from start to index 1
The stop index is excluded. Omitting start means "from the beginning"; omitting stop means "to the end."
Practice 11.3Index Practice
  1. Given animals = ["cat", "dog", "fish", "bird", "hamster"], what is the value of each of the following?

    a. animals[0]    b. animals[3]    c. animals[-1]    d. animals[-2]
  2. Using the same list, write a statement that changes "fish" to "turtle".
  3. What is the largest valid positive index for a list of 8 elements?
  4. Given nums = [5, 10, 15, 20, 25, 30], what does nums[2:5] return?
  5. Why does animals[5] cause an error for a 5-element list? What index would you use to access the last element?
  6. A classmate says "I'll use index 1 to get the first element." What misconception do they have? How would you correct it?

Arrays at an Introductory Level

In many textbooks and programming languages, the word array refers to a more specific kind of ordered collection than a general list. Understanding the distinction helps you read documentation, understand how computers actually store data, and prepare for Data Structures and Algorithms.

A traditional array has three characteristics that distinguish it from a Python list. First, an array has a fixed size: you specify how many elements it will hold when you create it, and that size cannot change. If you need more space, you must create a new, larger array. Second, every element in an array must be the same type: an array of integers holds only integers, an array of characters holds only characters. Third, elements are stored in contiguous memory locations — they sit right next to each other in the computer's memory, with no gaps.

This contiguous, fixed-size layout gives arrays a significant advantage: accessing any element by index is extremely fast, because the computer can calculate exactly where in memory to look. If the array starts at memory address A and each element takes B bytes, then the element at index i is at address A + (i × B). This is a simple arithmetic calculation that takes the same tiny amount of time regardless of which index you request or how large the array is.

Python's built-in list is more flexible than a traditional array: it can grow, shrink, and hold mixed types. But this flexibility has costs. The internal bookkeeping required to support dynamic resizing and mixed types makes Python lists somewhat slower than raw arrays for very large-scale numerical work. This is why Python's scientific computing library (NumPy) provides a true fixed-type array for applications such as data science and machine learning.

PropertyTraditional ArrayPython List
SizeFixed at creationDynamic — can grow or shrink
Element typesSame type onlyAny mix of types
Memory layoutContiguous (guaranteed)Managed internally
Access by indexO(1) — constant timeO(1) — constant time
Adding elementsNot supported (fixed size)append(), insert()
Typical useLow-level, performance-critical codeGeneral-purpose programming
Diagram — Array in Memory (Fixed Layout)

An integer array [10, 20, 30, 40] starting at memory address 1000, with each integer taking 4 bytes.

Addr
1000
1004
1008
1012
Value
10
20
30
40
Index
0
1
2
3

Element at index i is at address 1000 + (i × 4). This arithmetic is why array access is so fast.

Practice 11.4Arrays vs. Lists
  1. Name two properties of a traditional array that differ from a Python list.
  2. If an integer array starts at memory address 2000 and each integer takes 4 bytes, at what address is the element at index 5?
  3. Why can you access the millionth element of an array just as quickly as the first element?
  4. A data scientist processes millions of temperature readings, all stored as floating-point numbers, and needs maximum speed. Would a Python list or a fixed-type array be more appropriate? Explain.
  5. What limitation of traditional arrays does the Python list overcome? What does the Python list give up in exchange?
Sections 11.5 – 11.6
Strings as Sequences and Records — Structured Data for Real Entities
Strings as Sequences · Records and Fields

Strings as Sequences

You have been using strings since Chapter 7, but they are worth revisiting here because a string is not just a piece of text — it is a sequence of characters. Every character in a string has a position, just like every element in a list. You can access individual characters by index, slice substrings, find the length, and loop through characters one at a time. This means everything you learned about lists and indexes applies directly to strings.

The key difference between strings and lists is that strings are immutable: you cannot change an individual character in place. To create a modified version of a string, you must build an entirely new string. This immutability is by design — it makes strings safe to share between different parts of a program without worrying that one part will accidentally modify what another part is reading.

Example 11.5.1
Indexing and slicing a string
  • Setupword = "computing"
  • Index word[0] → "c" word[3] → "p" word[-1] → "g" len(word) → 9
  • Slice word[0:4] → "comp" word[4:] → "uting" word[:3] → "com"
  • Loop for ch in word: print(ch) # prints: c o m p u t i n g (one per line)

Immutability in Practice

Because strings are immutable, operations that seem to "change" a string actually produce a new string and leave the original unchanged. The original variable can then be assigned to the new string if you want the change to persist.

Example 11.5.2
String operations that produce new strings
  • Setupgreeting = "hello world"
  • Upper greeting.upper() → "HELLO WORLD" # greeting is still "hello world" — upper() returns a new string
  • Replace greeting.replace("world", "Python") → "hello Python" # original unchanged
  • Split greeting.split(" ") → ["hello", "world"] # produces a list of substrings
String methods return new strings (or other new objects). They never modify the original string.
MethodWhat It ReturnsExample
.upper()Uppercase version"hello".upper() → "HELLO"
.lower()Lowercase version"WORLD".lower() → "world"
.strip()Removes leading/trailing whitespace" hi ".strip() → "hi"
.replace(a, b)Replaces all occurrences of a with b"cat".replace("c","b") → "bat"
.split(sep)Splits into a list at each separator"a,b,c".split(",") → ["a","b","c"]
.startswith(s)True if string begins with s"Python".startswith("Py") → True
in operatorTrue if substring is present"py" in "python" → True
Practice 11.5Strings as Sequences
  1. Given s = "algorithm", evaluate: a. s[0]    b. s[-1]    c. s[2:5]    d. len(s)
  2. What is the difference between a mutable and an immutable object? Which category does a Python list fall into? Which does a Python string fall into?
  3. Write the Python expression that extracts just the word "data" from the string "data science" using a slice.
  4. Given name = " Margaret ", write a chain of method calls that produces "margaret" (lowercase, no spaces).
  5. A programmer writes s[0] = "A" where s = "algorithm", expecting to change the first character. What will happen and why?

Records

A list stores many items of the same kind in order. But many real-world entities consist of several different pieces of information that belong together. A student is not just a name — a student record includes a name, a student ID number, a grade level, a list of courses, and a GPA. These different pieces of information about the same entity are called fields, and the entire grouped set of fields is called a record.

Records allow programs to represent real-world entities naturally. Instead of storing names in one list, IDs in another list, and GPAs in a third list (and trying to keep them synchronized), a record keeps all the information about one student bundled together.

In Python, records can be represented in several ways depending on the complexity of the program. At the introductory level, a common approach is to use a dictionary (covered in the next section) for each record, where the field names are keys and the field values are values. Another approach is to use a class, which is covered in later courses. What matters conceptually is the idea: a record groups named fields into a single structured unit that represents one thing in the world.

Diagram — A Student Record with Named Fields
name"Carmen Reyes"
student_id10427
grade_level11
gpa3.7
enrolledTrue

One record representing one student. Each row is a field: a name (key) paired with a value. All five fields together form a single coherent unit.

Records differ from lists in an important way. A list is accessed by position — you retrieve item number 0, item number 1, and so on. A record is accessed by name — you retrieve the value of the "name" field or the "gpa" field. Accessing by name is more readable and less error-prone, because field names carry meaning while position numbers do not.

In many systems, a large collection of records is organized as a table: each row is one record, and each column is one field. A school database might have a table of thousands of student records, each with the same set of fields but different values. This is exactly how relational databases (covered in Chapter 18) organize information.

namestudent_idgrade_levelgpaenrolled
Carmen Reyes10427113.7True
David Park10388103.2True
Aisha Johnson10501123.9False
Practice 11.6Records
  1. What is a record? How does it differ from a list?
  2. A library system stores information about books. What fields would a book record likely contain? List at least five, and state the data type of each.
  3. Explain why accessing a record by field name is often preferable to accessing a list by index position.
  4. In the student table above, how many records are there? How many fields does each record have?
  5. Design a record for a product in an online store. What fields would it need? Organize them as a small table with example values.
Sections 11.7 – 11.8
Dictionaries, Stacks, and Queues — Key-Value Lookup and Ordered Access
Dictionaries and Maps · Stacks and Queues

Dictionaries and Maps

Suppose you want to look up a student's grade by their name. A list would require you to search through every element until you find the name you want — potentially checking thousands of entries. A dictionary solves this problem by organizing data as key-value pairs. Each key maps directly to one value, and looking up a value by key is extremely fast regardless of how many entries the dictionary contains.

The metaphor is exact: a physical dictionary maps each word (the key) to its definition (the value). A phone book maps each name (the key) to a phone number (the value). A dictionary data structure generalizes this pattern to any kind of key and any kind of value.

In Python, dictionaries are created using curly braces, with colons separating keys from values and commas separating pairs.

Example 11.7.1
Creating and using a dictionary
  • Create grades = { "Alice": 92, "Bob": 78, "Carmen": 95, "David": 85 }
  • Look up grades["Alice"] → 92 grades["Carmen"] → 95
  • Add grades["Eva"] = 88 # grades now has 5 entries
  • Update grades["Bob"] = 82 # updates Bob's grade from 78 to 82
  • Delete del grades["David"] # removes David's entry entirely
  • Check "Alice" in grades → True "Frank" in grades → False
Diagram — Dictionary as Key-to-Value Mapping
"Alice"92
"Bob"78
"Carmen"95
"David"85

Keys (left column) must be unique. Values (right column) may repeat. Lookup goes in one direction: key → value.

Key Rules for Dictionaries

RuleExplanationExample
Keys must be uniqueEach key appears at most once. Adding a key that already exists updates the value.d["x"] = 1; d["x"] = 2 → value is 2
Keys must be immutableStrings, numbers, and tuples work as keys. Lists do not.d[42] = "ok" works; d[[1,2]] = "no" fails
Values can be anythingValues can be numbers, strings, lists, other dicts, functions…d["scores"] = [90, 85, 92]
Lookup by missing key raises an errorRequesting a key that does not exist raises KeyErrorgrades["Frank"] → KeyError
Dictionaries vs. Lists — When to Use Each

Use a list when order matters and you access items by position. Use a dictionary when you need to access items by name or identifier. If you find yourself maintaining two parallel lists — one of names and one of matching values — that is a strong signal to use a dictionary instead.

Practice 11.7Dictionaries and Maps
  1. Create a Python dictionary that maps the names of three countries to their capital cities.
  2. Given the grades dictionary from Example 11.7.1, write the statement that looks up Carmen's grade.
  3. A programmer stores product prices as two parallel lists: names = ["apple","banana","cherry"] and prices = [0.99, 0.50, 2.49]. Rewrite this as a dictionary.
  4. Why must dictionary keys be unique? What happens if you add a key that already exists?
  5. A program needs to count how many times each word appears in a text. Which data structure would be most natural? Explain your reasoning.
  6. What error occurs when you try to look up a key that is not in the dictionary? How could you avoid that error?

Stacks and Queues

Lists and dictionaries organize data for flexible access. But sometimes the structure of a problem calls for a stricter rule about how items enter and exit the collection. Two fundamental restricted-access structures are the stack and the queue. Both are used throughout computer science, from web browsers to operating systems, from compilers to network routers.

The Stack — Last In, First Out

A stack is a collection in which items are added and removed from the same end, called the top. The rule is simple: the most recently added item is always the next item to be removed. This is called Last-In, First-Out, or LIFO.

The physical analogy is a stack of plates in a cafeteria. You place a clean plate on top of the stack. When someone takes a plate, they take it from the top. The plate added most recently is the one removed first. A plate deep in the stack cannot be reached until all the plates on top of it are removed.

The two fundamental stack operations are push (add an item to the top) and pop (remove the item from the top). In Python, a list can serve as a stack: append() acts as push, and pop() without an argument removes from the end (the top of the stack).

Diagram — Stack: Push and Pop

After push(10), push(20), push(30)

← TOP
30
20
10

30 was pushed last. It will be popped first.

After pop() → returns 30

← TOP
20
10

30 is gone. Now 20 is at the top.

Example 11.8.1
Using a Python list as a stack
  • Code stack = [] stack.append("page1") # push stack.append("page2") # push stack.append("page3") # push # stack is ["page1", "page2", "page3"] last = stack.pop() # pop → "page3" # stack is now ["page1", "page2"]
  • Real useThis is exactly how a browser's Back button works. Each page you visit is pushed onto the history stack. Pressing Back pops the most recent page, returning you to the previous one.

The Queue — First In, First Out

A queue is a collection in which items are added at one end (the back or rear) and removed from the other end (the front). The rule is: the first item added is the first item removed. This is called First-In, First-Out, or FIFO.

The physical analogy is a line of people waiting at a ticket counter. The person who arrived first is served first. New arrivals join at the back of the line. Nobody cuts ahead. The two fundamental queue operations are enqueue (add to the back) and dequeue (remove from the front).

Diagram — Queue: Enqueue at Back, Dequeue at Front

Queue after enqueue("A"), enqueue("B"), enqueue("C")

FRONT
A
B
C
BACK

dequeue() removes "A" from the front. enqueue("D") adds "D" to the back. Order is preserved: first in, first out.

Example 11.8.2
Queue behavior — tracing operations
  • Startqueue = []
  • Enqueue queue.append("job1") → ["job1"] queue.append("job2") → ["job1", "job2"] queue.append("job3") → ["job1", "job2", "job3"]
  • Dequeue queue.pop(0) → "job1" # removes from front # queue is now ["job2", "job3"]
  • Real useThis is how a print queue works. The first print job sent to the printer is the first one printed. Later jobs wait at the back.
Note: For performance-critical queues, Python's collections.deque is preferred over list.pop(0), but the conceptual behavior is identical.
PropertyStackQueue
Access ruleLIFO — Last In, First OutFIFO — First In, First Out
Add operationPush (to top)Enqueue (to back)
Remove operationPop (from top)Dequeue (from front)
Physical analogyStack of platesWaiting line
Real-world useBrowser history, undo/redo, function callsPrint queues, task scheduling, message passing
Practice 11.8Stacks and Queues
  1. Trace the following stack operations and show the contents of the stack after each step.

    Start: empty stack
    push(5) → push(12) → push(7) → pop() → push(3) → pop() → pop()

    What is returned by each pop(), and what does the stack contain at the end?
  2. Trace the following queue operations and show the contents of the queue after each step.

    Start: empty queue
    enqueue("A") → enqueue("B") → enqueue("C") → dequeue() → enqueue("D") → dequeue()

    What is returned by each dequeue(), and what does the queue contain at the end?
  3. Explain in your own words why a browser's Back button is best modeled by a stack rather than a queue.
  4. A hospital emergency room triages patients in order of arrival. Which structure — stack or queue — best models the waiting room? Explain.
  5. A text editor's "Undo" feature reverses the most recent action, then the next most recent, and so on. Which structure does it use? What principle applies?
  6. Could you implement both a stack and a queue using a Python list? What Python operations would you use for each? What is the key difference in which end of the list each structure uses?
Sections 11.9 – 11.10
Choosing a Structure and Seeing Them in Real Software
Choosing a Data Structure · Data Structures in Real Software

Choosing a Data Structure

Understanding each data structure individually is the first step. The next step — and the one that actually matters in programming — is knowing which structure to choose when faced with a new problem. The key insight is this: the right data structure is the one whose natural operations match the operations your program needs to perform.

To choose wisely, ask yourself a series of questions about the problem. First, what kind of data are you storing, and how much? Second, how will you access the data? By position? By name? By order of arrival? Third, what operations will you perform most often? Adding items? Removing items? Searching? Iterating in order? Fourth, does order matter? Fifth, do you need fast lookup by a specific identifier?

Decision Framework — Choosing a Data Structure

Use a list when you need ordered items you access by position, and the order of items matters. Good for sequences, histories, and ordered sets.

Use an array when all items are the same type, the size is known and fixed, and you need maximum performance for numerical work.

Use a string when your data is text — a sequence of characters you will process, search, or split.

Use a record when you need to group multiple named fields describing a single real-world entity.

Use a dictionary when you need to look up values by a meaningful name or identifier — not by position. Good for any name-to-value mapping.

Use a stack when the most recent item added must be the first item removed (LIFO). Good for undo, back navigation, and tracking nested operations.

Use a queue when items must be processed in the order they arrived (FIFO). Good for scheduling, waiting lists, and ordered task processing.

StructureOrdered?Access byAdd/RemoveTypical Use
ListYesIndex (position)Any end or middlePlaylists, to-do lists, grade rolls
ArrayYesIndex (position)Not typicallyPixels, sensor readings, numerical data
StringYes (chars)Index (position)Immutable — build newNames, messages, file paths, URLs
RecordNo orderingField nameTypically fixed fieldsStudent, product, employee, book
DictionaryNo ordering*Key (name)Any keyWord counts, lookup tables, settings
StackLIFOTop onlyTop onlyUndo, browser Back, call stack
QueueFIFOFront onlyBack onlyPrint jobs, task scheduling, messaging

*Python dictionaries preserve insertion order as of Python 3.7, but lookup is still by key, not position.

Example 11.9.1
Matching a problem to a structure — three scenarios
  • Scenario AA music app needs to store a user's playlist: 50 songs, played in order, with the ability to add songs and skip to the next one.
    Best choice: List. Order matters. Access is by position (current position in playlist). New songs are added to the end.
  • Scenario BA system needs to store student grades indexed by student name, and look up any student's grade instantly.
    Best choice: Dictionary. Lookup is by name, not position. Fast key-based access is the core operation.
  • Scenario CA web server receives requests from users. Each request must be handled in the order it was received. New requests queue up when the server is busy.
    Best choice: Queue. First request received must be handled first (FIFO). New requests join the back; the server handles from the front.
Practice 11.9Choosing a Data Structure
  1. For each situation below, name the most appropriate data structure and explain your reasoning.

    a. A phone book that maps names to phone numbers.
    b. A set of high scores in a video game, displayed in order from highest to lowest.
    c. A shipping system that processes packages in the order they arrive at the warehouse.
    d. The undo history in a word processor (most recent action undone first).
    e. A store's catalog of 10,000 products, each with a name, price, and quantity in stock.
    f. A sensor recording temperature once per second, storing 86,400 readings per day.
  2. A programmer uses a list where a dictionary would be more appropriate — storing names in one list and phone numbers in a parallel list. Describe a specific problem this approach would cause.
  3. Could you model a queue using a list? Write pseudocode showing how enqueue and dequeue would work using list operations.
  4. What is the key question to ask yourself when deciding between a list and a dictionary?

Data Structures in Real Software

Data structures are not abstract exercises — they are the working machinery of every piece of software you use. Understanding which structures appear in real systems helps you see why the concepts in this chapter are foundational rather than academic.

Web browsers use stacks to implement the Back button: each URL you visit is pushed onto a history stack; pressing Back pops the most recent URL. They also use queues to manage resources being downloaded in the background.

Search engines use sophisticated structures to index billions of web pages, but at their core they maintain enormous dictionaries: each word in their index maps to a list of pages where that word appears. Looking up a search term means looking up its key in this dictionary.

Social networks store user profiles as records — each user has an ID, a name, a list of posts, a list of friends, and other fields. Friend lists are themselves lists of user IDs. Finding a user's profile quickly requires dictionary-style lookup by user ID.

Video games store the positions, attributes, and states of every game object. An enemy might be a record containing location coordinates, health points, speed, and current action. Lists of enemies are processed every frame to update movement and check collisions.

Operating systems use queues to schedule processes. When several programs want to use the CPU at the same time, a scheduling queue determines whose turn it is. They also use stacks to manage function calls: each call pushes a frame onto the call stack, and returning from a function pops it off.

Databases organize data as large tables of records. Each row is one record; each column is a field. Lookup by primary key (like a student ID or product code) is implemented with structures designed for fast key-based search, building on the dictionary concept at a much larger scale.

Network routers maintain routing tables — dictionaries that map destination IP addresses to the next network hop. Incoming packets are often placed in queues while the router decides where to forward them.

Real SystemData Structure UsedPurpose
Web browserStackBack button history
Search engineDictionaryWord → page lookup (inverted index)
Social networkRecords + listsUser profiles and friend connections
Video gameRecords + listsGame objects and their attributes
Operating systemQueue + stackProcess scheduling and function call management
DatabaseTables (records)Persistent structured data storage
Network routerDictionary + queueRouting table and packet buffer
CompilerStackParsing nested expressions and function calls
Practice 11.10Real-World Applications
  1. Explain how a browser's Back button uses a stack. What happens when you press Forward? (Hint: what might a second stack be used for?)
  2. A search engine's inverted index maps each word to a list of pages containing that word. If someone searches for "climate change", what two lookups does the search engine perform? What does it do with the two resulting lists?
  3. An operating system has three programs waiting to use the CPU. Program A arrived first, then B, then C. In what order will the CPU handle them, assuming a basic FIFO queue? What would happen if a stack were used instead?
  4. Think of a software application you use regularly (a game, a map app, a note-taking tool, a music player). Identify at least two data structures that application probably uses internally and explain your reasoning.
  5. A compiler reads through your code and must match every opening parenthesis ( with a closing parenthesis ), including nested ones like ((a + b) * (c - d)). Explain why a stack is the natural structure for checking that parentheses are balanced.

Chapter Summary

Key Terms Review

data structure
An organized way to store and access a collection of data so that specific operations can be performed efficiently.
list
An ordered, mutable collection of elements accessible by index. Elements can be any type and can be added, removed, or changed.
element
A single item stored in a list or other collection.
index
The position of an element in a list or string, counted from zero. Valid indexes run from 0 to (length − 1).
zero-based indexing
The convention that the first element in a sequence is at position 0, the second at position 1, and so on.
slice
A contiguous portion of a list or string, specified with a start and stop index (stop is excluded). Returns a new object.
array
A collection of fixed size holding elements of a single type, stored in contiguous memory. Enables constant-time access by index via address arithmetic.
mutable
Can be changed in place after creation. Python lists are mutable; Python strings are not.
immutable
Cannot be changed in place after creation. Strings are immutable; operations on them produce new strings.
record
A group of named fields representing a single real-world entity. Accessed by field name rather than index position.
field
One named piece of information within a record. A student record might have fields for name, ID, grade level, and GPA.
dictionary
A collection of key-value pairs. Each key is unique and maps to exactly one value. Lookup by key is very fast.
key
The identifier used to look up a value in a dictionary. Keys must be unique and immutable within a dictionary.
value
The data associated with a key in a dictionary. Values can be any type and may repeat across different keys.
stack
A collection following Last-In, First-Out (LIFO) order. Items are pushed to and popped from the top. Used for undo and navigation history.
queue
A collection following First-In, First-Out (FIFO) order. Items are enqueued at the back and dequeued from the front. Used for scheduling and waiting lines.
LIFO
Last-In, First-Out. The ordering principle of a stack: the most recently added item is the next to be removed.
FIFO
First-In, First-Out. The ordering principle of a queue: the first item added is the first item removed.

Debugging and Error Analysis

Each item describes a mistake. Identify the error and write a corrected version or explanation.

Mistake 1 — Off-by-one index
grades = [88, 95, 71]; print(grades[3])

The list has 3 elements at indexes 0, 1, 2. Index 3 does not exist. What error will occur at runtime? Write the correct index to access the last element.

Mistake 2 — Modifying a string character in place
s = "hello"; s[0] = "H"

Strings are immutable. This raises a TypeError. How would you correctly create the string "Hello" from "hello"?

Mistake 3 — Duplicate key in a dictionary
d = {"a": 1, "b": 2, "a": 3}; print(d["a"]) # expects 1

Keys must be unique. The second "a" overwrites the first. What value will print? Explain why.

Mistake 4 — Using pop() on a queue
queue = ["A", "B", "C"]; queue.pop() # intends to dequeue

pop() without an argument removes from the end, giving "C" — which is the most recently added item (LIFO). This is stack behavior, not queue behavior. Write the correct dequeue operation for the front.

Mistake 5 — Accessing a missing dictionary key
grades = {"Alice": 90}; print(grades["Bob"])

Accessing a key that does not exist raises a KeyError. How could you safely check whether "Bob" is in the dictionary before accessing it?

Skill Practice

Part AList and Index Practice
  1. Given cities = ["Cairo", "Paris", "Tokyo", "Lima", "Oslo"], answer each question.

    a. What is cities[2]?
    b. What is cities[-1]?
    c. What does len(cities) return?
    d. What does cities[1:4] return?
    e. Write a statement to change "Paris" to "Rome".
    f. Write a statement to add "Sydney" to the end of the list.
  2. A list temps holds 7 daily temperature readings. Write the Python for loop that prints every element in the list on a separate line.
  3. What is the valid range of positive indexes for a list of 12 elements?
Part BStrings as Sequences
  1. s = "programming": What is s[0]?
  2. What is s[-3]?
  3. What is s[3:7]?
  4. What does len(s) return?
  5. Write the expression to get "PROGRAMMING".
  6. Write the expression that returns True if "gram" appears in s.
Part CDictionary Practice
  1. Create a dictionary capitals that maps three countries to their capitals. Then write the lookup to get the capital of the second country you entered.
  2. Given inventory = {"pen": 40, "notebook": 15, "stapler": 7}, write statements to:

    a. Look up the count of notebooks.
    b. Add a new item: "tape" with a count of 22.
    c. Update the count of pens to 35.
    d. Check whether "scissors" is in the inventory.
  3. Explain in one sentence why a dictionary is better than a pair of parallel lists for a phone book application.
Part DStack and Queue Tracing
  1. Trace the following stack operations. After each operation, write the state of the stack (bottom to top).

    push(1)  ·  push(2)  ·  push(3)  ·  pop()  ·  push(4)  ·  pop()  ·  pop()
  2. Trace the following queue operations. After each operation, write the state of the queue (front → back).

    enqueue("X")  ·  enqueue("Y")  ·  enqueue("Z")  ·  dequeue()  ·  enqueue("W")  ·  dequeue()

Structure Selection Questions

For each scenario, name the most appropriate data structure and write 1–2 sentences explaining your choice.

  1. A navigation app stores the sequence of turns a user must take: left on Elm St, right on Oak Ave, straight for 2 miles, etc.
  2. A customer service call center handles incoming calls in the order they are received.
  3. A program maps zip codes to city names for fast lookup during address verification.
  4. A scientific instrument records 10,000 pressure readings per second, all as floating-point numbers.
  5. A hospital maintains a patient record containing name, date of birth, blood type, allergies, and a list of past visits.
  6. A text editor needs to support unlimited Undo operations, always reversing the most recent change first.
  7. A music streaming app stores the lyrics of a song as a single block of text for display and search.
  8. A voting system counts how many votes each candidate received across thousands of ballots.

Real-World Application Questions

  1. A web browser has a Back button and a Forward button.

    a. Explain how two stacks can implement both buttons.
    b. What happens to the Forward stack when you navigate to a new page while looking at a page in the middle of your history?
  2. An email application displays messages in a mailbox. You can read emails, mark them as read, delete them, or search for a message by subject. Which data structures would be useful for representing the mailbox and the individual messages? Explain each choice.
  3. Think about how a streaming service (like a music or video platform) tracks what you have listened to or watched recently. What data structures would help them store: (a) your recent history in order, (b) your ratings for each title, and (c) your profile information? Explain each.

Chapter 11 Checkpoint

Chapter 11 Checkpoint
Complete without assistance — assesses all key skills and concepts from Chapter 11
Section 1 — Vocabulary and Concepts
  1. Define data structure and explain in one sentence why the choice of structure matters.
  2. Explain the difference between a mutable and an immutable collection. Give one example of each from this chapter.
  3. What is the difference between a list and a dictionary? When is each appropriate?
  4. Define LIFO and FIFO. Which structure uses each principle?
Section 2 — Index and List Skills
  1. Given data = [4, 8, 15, 16, 23, 42]:
    a. What is data[0]?
    b. What is data[-1]?
    c. What does data[2:5] return?
    d. Write a statement to change 8 to 9.
    e. What index error would data[6] cause?
  2. Write a Python for loop that prints every element of a list called scores on a separate line.
Section 3 — Dictionary Skills
  1. Given colors = {"sky": "blue", "grass": "green", "sun": "yellow"}:
    a. Write the lookup for "grass".
    b. Add an entry: "ocean" maps to "blue".
    c. Change "sun" to map to "orange".
    d. Write the expression that returns True if "moon" is a key.
Section 4 — Stack and Queue Tracing
  1. Trace these stack operations and give the final state and each return value:
    push(5) · push(8) · push(2) · pop() · push(6) · pop()
  2. Trace these queue operations and give the final state and each return value:
    enqueue("R") · enqueue("G") · enqueue("B") · dequeue() · enqueue("Y")
Section 5 — Structure Selection
  1. Name the best data structure for each scenario and give a one-sentence justification:
    a. Tracking the order of tasks submitted to a shared printer.
    b. Looking up a product price by product code.
    c. Storing the sequence of chess moves made in a game.
    d. Implementing Undo in an image editor.
Looking Ahead
Chapter 12: Searching, Sorting, and Efficiency

Chapter 11 gave you the containers — the data structures that hold information. Chapter 12 asks a new question: once information is stored in a structure, how do you find specific items, and how do you arrange them in order? You will learn linear search, binary search, and the basic principles of sorting algorithms. More importantly, you will learn to think about efficiency: why some approaches are dramatically faster than others as data grows larger, and how computer scientists describe and compare algorithmic performance. The intuition for Big-O that you will develop in Chapter 12 connects directly to the structures you learned here — the right structure makes the right search algorithm possible.

MGU Library Connection
  • Data Structures Reference — Appendix F of this textbook
  • Python-Style Code Reference — Appendix D of this textbook: lists, dictionaries, strings
  • Chapter 7: Variables, Types, and Expressions — lists and strings introduced
  • Chapter 12: Searching, Sorting, and Efficiency — algorithms that operate on these structures
  • Chapter 14: Files, Tables, and Data Processing — records and tables in persistent storage
  • Chapter 18: Databases and Information Systems — large-scale record management
  • Data Structures and Algorithms (MGU CS Series) — full treatment of linked lists, trees, hash tables, graphs