Searching and Sorting Algorithms
Linear search, binary search, bubble sort and merge sort: how each one moves through the data, how to trace it, and how to justify choosing one over another.
Linear search and binary search
Linear search
Linear search starts at the first item and checks each one in turn until it finds the target or runs out of list.
FUNCTION linearSearch(items, target)
FOR position FROM 0 TO LENGTH(items) - 1 DO
IF items[position] = target THEN
RETURN position
END IF
END FOR
RETURN -1
END FUNCTIONIts strength is that it makes no demands on the data. The list can be in any order, and no preparation is needed. Its weakness is speed: on a list of n items the worst case is n comparisons, so searching a million records could mean a million checks.
Binary search
Binary search only works on a sorted list. It looks at the middle item, and because the list is sorted, one comparison tells it which half the target must be in. The other half is discarded entirely.
- Find the middle item of the search area.
- If it is the target, stop.
- If the target is smaller, discard the middle item and everything above it.
- If the target is larger, discard the middle item and everything below it.
- Repeat on what is left, until the target is found or nothing remains.
FUNCTION binarySearch(items, target)
SET low TO 0
SET high TO LENGTH(items) - 1
WHILE low <= high DO
SET mid TO (low + high) DIV 2
IF items[mid] = target THEN
RETURN mid
ELSE IF items[mid] < target THEN
SET low TO mid + 1
ELSE
SET high TO mid - 1
END IF
END WHILE
RETURN -1
END FUNCTIONWorked example
Find 23 in [4, 8, 15, 16, 23, 42, 50].
| Step | Search area | Middle | Comparison | Action |
|---|---|---|---|---|
| 1 | 4 to 50 | 16 | 23 is greater than 16 | Discard 4, 8, 15, 16 |
| 2 | 23 to 50 | 42 | 23 is less than 42 | Discard 42, 50 |
| 3 | 23 only | 23 | Found | Stop |
Three comparisons. Linear search would have taken five.
Each linear comparison rules out one item. Each binary comparison rules out half of everything that is left. On large lists that difference is the whole ball game, but it is bought with the requirement that the list is sorted first.
- Linear search looks at every item in turn from the start, so it can be slow.
- Binary search checks the middle and throws half the list away each time.
- 3 looks against 10. The longer the list, the bigger the gap, but binary search needs the list sorted.
Bubble sort
Bubble sort repeatedly walks through the list comparing each pair of neighbours and swapping them if they are the wrong way round. After the first full pass the largest value has been carried all the way to the end, which is where the name comes from.
PROCEDURE bubbleSort(items)
SET swapped TO TRUE
WHILE swapped = TRUE DO
SET swapped TO FALSE
FOR i FROM 0 TO LENGTH(items) - 2 DO
IF items[i] > items[i + 1] THEN
SET temp TO items[i]
SET items[i] TO items[i + 1]
SET items[i + 1] TO temp
SET swapped TO TRUE
END IF
END FOR
END WHILE
END PROCEDURETracing one pass
Start with [7, 3, 9, 2].
- Compare 7 and 3. Wrong order, swap:
[3, 7, 9, 2] - Compare 7 and 9. Correct order, leave:
[3, 7, 9, 2] - Compare 9 and 2. Wrong order, swap:
[3, 7, 2, 9]
End of pass one. 9 is now in its final position. Pass two produces [3, 2, 7, 9], pass three produces [2, 3, 7, 9], and pass four makes no swaps at all, which is how the algorithm knows it has finished.
Why the swapped flag matters
Without the flag the algorithm has no way of knowing the list is already sorted, and would carry on making pointless passes. With it, a list that is already in order is confirmed sorted in a single pass. This is why bubble sort is respectable on nearly sorted data and dreadful on everything else.
Questions ask both "how many passes" and "how many comparisons". One pass over a list of n items makes n minus 1 comparisons. Read which one is being asked for.
- Compare two neighbours, and if they are the wrong way round, swap them.
- Work along the list. A big value is carried all the way to the end.
- After a pass the last item is in its final place, so the next pass can be shorter.
- Repeat until a whole pass makes no swaps.
Merge sort
Merge sort uses divide and conquer. It splits the list in half over and over until every piece holds a single item, then builds the answer back up by merging pairs of sorted pieces.
The insight it rests on is that a list of one item is already sorted, and that merging two sorted lists is easy: compare the first item of each, take the smaller, repeat.
Divide
[6, 2, 8, 4, 1] splits into [6, 2] and [8, 4, 1], which split into [6], [2], [8] and [4, 1], and finally [4, 1] splits into [4] and [1].
Merge
- Merge
[6]and[2]to get[2, 6] - Merge
[4]and[1]to get[1, 4] - Merge
[8]and[1, 4]to get[1, 4, 8] - Merge
[2, 6]and[1, 4, 8]to get[1, 2, 4, 6, 8]
Why it is fast, and what it costs
Splitting a list of n items in half repeatedly takes about log2n rounds, and each round of merging touches every item once. On a list of 1000 items that is roughly 10 rounds of 1000 operations, about 10000 steps, against bubble sort's worst case of nearly 500000. The comparison is not close.
The cost is memory. Merge sort has to hold the sub lists separately while it merges them, so it needs additional space roughly the size of the original list. Bubble sort works in place and needs room for a single temporary variable. On a device with very little RAM that trade off can decide the choice.
- Divide the list in half, again and again.
- Stop when every group is a single item. One item is already sorted.
- Merge groups back together, taking the smaller front item each time, until one sorted list is left.
Choosing and comparing
Edexcel asks you to compare algorithms and justify a choice. The marks are in the reasoning, so learn the trade offs rather than a ranking.
| Linear search | Binary search | |
|---|---|---|
| List must be sorted | No | Yes |
| Worst case on n items | n comparisons | About log2n comparisons |
| Best case | 1 comparison | 1 comparison |
| Good for | Small or unsorted lists, one off searches | Large lists that are already sorted or searched repeatedly |
| Bubble sort | Merge sort | |
|---|---|---|
| Method | Repeated swapping of neighbours | Divide the list, then merge sorted pieces |
| Speed on large lists | Very slow | Much faster and consistent |
| Extra memory | Almost none, sorts in place | Significant, sub lists are held separately |
| Easiest to write | Yes | No |
| Good for | Small or nearly sorted lists | Large lists where speed matters |
Building the justification
The structure that scores is: name the algorithm, give the property of the data that makes it suitable, then give the consequence.
"For a list of 50000 sorted product codes searched thousands of times a day, binary search is the better choice. The list is already sorted, so the precondition costs nothing, and each comparison eliminates half of the remaining codes, so a search takes at most about 16 comparisons instead of up to 50000. Over thousands of searches that difference is enormous."
That is one mark. The marks after it come from saying why it is faster, that it requires a sorted list, and what that requirement costs if the data is not already sorted.
Sorting algorithm visualiser
Run bubble, insertion, merge and quick sort side by side and count the comparisons. This tool needs JavaScript, so turn it on to use it. Everything you need to answer the exam question is explained in the text above.
Key terms you must be able to define
- Linear search
- A search that checks each item in a list in turn from the start until the target is found or the end is reached.
- Binary search
- A search that repeatedly examines the middle item of a sorted list and discards the half that cannot contain the target.
- Bubble sort
- A sort that repeatedly compares adjacent items and swaps them if they are in the wrong order until a pass makes no swaps.
- Merge sort
- A sort that repeatedly divides the list into halves until each holds one item, then merges the pieces back together in order.
- Divide and conquer
- A strategy that solves a problem by breaking it into smaller instances of the same problem and combining the results.
- Pass
- One complete run through the list by a sorting algorithm.
- Comparison
- One test of two values against each other, used as the standard measure of how much work a search or sort does.
- Efficiency
- A measure of the resources an algorithm uses, usually the number of comparisons or steps and the amount of memory required.
- In place
- A description of an algorithm that rearranges the data using almost no additional memory.
Flashcards
Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.
Reach the top grade on this topic
Every question here rewards the same two moves: trace accurately and justify with a trade off.
Traces must show the state after each step. A merge sort question asking you to show the divide stage wants every level of splitting written out, not just the final answer. A bubble sort question asking for the list after two passes wants the list after pass one as well, because that is where the working marks live.
Every advantage has a matching cost. Binary search is faster but demands a sorted list. Merge sort is faster but demands more memory. Bubble sort is slow but simple and works in place. An answer that gives an advantage without acknowledging the cost is an average answer.
Quote numbers when you can. "Binary search would take at most 17 comparisons on 100000 records instead of up to 100000" is far stronger than "binary search is quicker", and it takes the same amount of time to write.
- Be able to trace a binary search on a sorted list of nine items and state the number of comparisons
- Be able to give the list after each pass of a bubble sort on a list of five values
- Be able to draw the full divide and merge stages of a merge sort on six values
- Be able to state the worst case number of comparisons for linear and binary search on n items
- Be able to justify a choice of algorithm for a stated scenario in three sentences
Mistakes that cost marks here
- Using binary search on an unsorted list. It does not simply run more slowly, it returns the wrong answer.
- Confusing passes with comparisons. A single pass over n items makes n minus 1 comparisons.
- Saying merge sort is better than bubble sort in every way. Merge sort needs considerably more memory because the sub lists must be stored.
- Forgetting that bubble sort stops early when a pass makes no swaps, which is what makes it acceptable on nearly sorted data.
- Writing that linear search is 'always slow'. On a small list, or when the target is near the front, it is perfectly efficient and needs no sorting first.
- Splitting a merge sort list into groups of two and stopping there. The division continues until every sub list holds exactly one item.
Binary search halves the list every comparison, so ten comparisons cover 1024 items and twenty cover just over a million. That is why a phone can look a word up in a dictionary of half a million entries the instant you stop typing.
Knowledge check
Exam-style questions
Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.
- LFewer comparisons are needed so the search is faster
- LEach comparison eliminates half of the remaining items
A binary search needs far fewer comparisons than a linear search on a large list, so it finds the item much more quickly. This is because each comparison removes half of the remaining items from the search, whereas a linear search only removes one item at a time.
- LAdjacent pairs of items are compared
- LThey are swapped if they are in the wrong order
- LThis is repeated in further passes through the list
- LThe algorithm stops when a complete pass makes no swaps
The algorithm compares the first two items, 5 and 1, finds them in the wrong order and swaps them to give 1, 5, 4, 2. It then compares 5 and 4, swaps them to give 1, 4, 5, 2, and compares 5 and 2, swapping them to give 1, 4, 2, 5, which completes the first pass and leaves the largest value at the end. A second pass compares 1 and 4 with no swap, then 4 and 2 with a swap, giving 1, 2, 4, 5. A third pass makes no swaps at all, and because nothing needed to move the algorithm knows the list is sorted and stops.
- LThe list is repeatedly divided in half
- LUntil each sub list contains only one item, which is sorted by definition
- LPairs of sub lists are then merged back together
- LDuring each merge the first item of each sub list is compared and the smaller is taken first
A merge sort begins by dividing the list into two halves, then dividing each of those halves again, and continuing until every sub list contains exactly one item. A list of one item is already in order, which is why this is a sensible place to stop. The algorithm then merges the sub lists back together in pairs: to merge two sorted sub lists it compares the first item of each, takes whichever is smaller and places it into the new list, then repeats until both sub lists are empty. Each merge produces a longer sorted list, and the process continues until a single sorted list containing every original item remains.
- LThe records are already sorted, so the requirement of binary search is met at no extra cost
- LEach comparison halves the number of records still to be searched
- LAt most about 18 comparisons are needed instead of up to 200000
- LBecause the search is repeated thousands of times a day the saving is large, reducing processing time and server load
A binary search is the right choice here because the records are already held in order of customer number, so the one condition binary search imposes is already satisfied and costs nothing to meet. Each comparison in a binary search discards half of the records still under consideration, so a file of 200000 records is reduced to one in at most about eighteen comparisons, since two to the power eighteen is greater than 200000. A linear search would in the worst case examine all 200000 records to reach the same answer. Because the search runs several thousand times a day the difference is not a technicality: it is the difference between a few tens of thousands of comparisons a day and hundreds of millions, which directly affects response time for the user and the processing load on the company's servers.
- LBubble sort repeatedly swaps adjacent items while merge sort divides and merges
- LMerge sort is significantly faster on large lists
- LBubble sort uses almost no extra memory because it sorts in place
- LMerge sort requires additional memory to store the sub lists
- LBubble sort is better on small or nearly sorted lists, merge sort on large lists where speed matters
Bubble sort works by repeatedly comparing adjacent items and swapping any that are in the wrong order, continuing until a pass makes no swaps, whereas merge sort divides the list in half until each part holds one item and then merges the parts back together in order. On a large list merge sort is dramatically faster, because the number of steps grows roughly in proportion to n multiplied by the logarithm of n rather than n squared. The trade off is memory: bubble sort works in place and needs room for only a single temporary variable, while merge sort must hold the sub lists separately and so needs extra space roughly equal to the size of the original list. Bubble sort is therefore the better choice for a short list, or one that is already nearly in order, where its simplicity and low memory use matter more than raw speed, for example sorting a class of thirty test scores on a microcontroller. Merge sort is the better choice when a large volume of data must be sorted quickly and there is memory to spare, for example ordering a hundred thousand search results on a server.