Announcements
- Welcome back at long last
- If only it were on more pleasant terms :\
- No quiz today since, well, last time was the exam :B
- Notes about project 3’s methods
isFullSolution
andreject
are what you should work on first- those can be tested without doing anything else
- they’re subtly different though - be sure not to reject solutions with empty cells!
extend
should find the next available empty cell- if all cells are full, it should return
null
- once it finds an empty cell, it should put a
1
there- don’t forget to make a copy!
- make a method to copy a board.
- if all cells are full, it should return
next
should find the most-recently-placed number and make it 1 bigger- if the most-recently-placed number was a 9, it should return
null
- if the most-recently-placed number was a 1, it should make it a 2; 2 -> 3; 3 -> 4; etc.
- again, don’t forget to make a copy!
- if the most-recently-placed number was a 9, it should return
- keeping track of which is the “most-recently-placed” number can be tricky
- there are many ways to do it
- you are allowed to change the code (parameters to functions, etc)
- you’re not even required to store the board as an
int[][]
!
Ordering
- A total ordering is a mathematical concept
- Basically, it boils down to: “you can compare any two things; those two things will either be equal or one will come after the other; and comparison is transitive”
- Numbers have a total ordering
- You can pick any two numbers
- They will either be equal (3 = 3) or will come in one specific order (3 < 4, not 4 < 3)
- Comparison is transitive (3 < 4 and 4 < 5, so 3 < 5)
- Words have a total ordering, too
- Depending on the language, of course
- You can’t sort a collection of things that don’t have a total ordering!
- Or in Java parlance, you can’t sort a collection of things that don’t implement
Comparable
.
- Or in Java parlance, you can’t sort a collection of things that don’t implement
Sorting
- Unordered data is useful in a lot of cases, but many situations require ordered data
- Sorting is putting things in some kind of order
- Ordered data is easier to search through (remember binary search?)
- Ordered data is easier for people to look at
- Many algorithms - not just searching - require ordered data to work properly
- So lots of effort has gone into making good (efficient!) sorting algorithms.
- Automated sorting actually goes back to the 1800s (!)
- Punchcard sorters existed then and were used well into the 1960s and 1970s
- Early uses were for the census, taxes, and payroll
- An entire industry of “unit record equipment” did many of the things we use computers for today
- Think of them as “the great-grandparent of spreadsheets and databases”
- A sorted array is such that:
- For all indices and , if , then .
- Don’t be fooled by the “less-than-or-equals” sign - this works for more than just numbers
- And that could be a greater-than-or-equals sign and still work just as well.
- Ascending order means that we start with the “smallest” value and go up
- Descending order means the opposite: start with the “biggest” value
- Duplicate items require some consideration…
- For simple things like numbers, duplicates are no issue
- But what about people’s names?
- If they have a family name and a given name…
- If you have 5 people with the same family name, what order should they go in?
- They’re not really duplicates…
- We’ll come back to this next time
Finding a minimum
- Maybe you’ve done this before (401? 0007?)
- This is sort of like a “running total” algorithm
- Keep a “smallest” value
- Loop over array and compare each against the smallest
- If the value in the array is smaller than the current smallest, it becomes the new “champion”
- How many steps does this take?
- iterations
- How many comparisons do we do?
- comparisons
- We can find any extremum (minimum, maximum, whatever) this way, and it’s always gonna be linear
Selection Sort
- We now know enough to make a simple sorting algorithm: selection sort.
- It’s called this because we select one item from the array, over and over.
- Let’s say I have this array:
- If I want to sort it in ascending order…
- Which item do I want to select to be the first item in the array?
- The smallest. The minimum.
- So, 1.
- Let’s make a second array that contains the sorted items:
- And let’s remove 1 from the original array:
- Now we just repeat the process.
- Select the smallest (minimum).
- Remove it from the original array.
-
Put it at the end of the new array.
- How much space do we need for each step?
- Well the unsorted array is getting 1 smaller, and the sorted array is getting 1 bigger…
- The space is constant.
- So it seems silly to need 2 arrays.
- Let’s make it work in-place - no second array needed.
- For
i = 0; i < n; i++
- Select the smallest (minimum), starting at item
i
. -
Swap it with item
i
.
- Select the smallest (minimum), starting at item
- This way lends itself to being written recursively very easily.
- Find minimum of
array[i to end]
- Swap minimum with
array[i]
- Recurse with
i + 1
- Find minimum of
- For
- What is the runtime?
- How many times does the outer loop run?
- How long does it take to find the minimum?
- How long does it take to swap two items?
- If we multiply all those together, it’s
- How many comparisons do we do?
- again, since we do comparisons to find the minimum on each of iterations
Bubble sort
- Here’s another simple algorithm
- We look for inversions: when a pair of items are in the wrong order.
- So, if we saw
5, 3
, that’s an inversion - cause 5 should come after 3.
- So, if we saw
- So here’s the algorithm:
- For
i = 0; i < n - 1; i ++
- If
A[i]
>A[i + 1]
…- Swap them, and set
i = 0
. (start over!)
- Swap them, and set
- If
- When this loop exits, no inversions have been found, and the array is sorted.
- For
-
Seems kind of silly, but it does work:
- Notice how sometimes numbers will move backwards through the array
- This is why it’s called bubble sort - the values sort of “bubble” through the array slowly
- It doesn’t go strictly beginning-to-end like selection sort.
- And the values don’t end up in their final positions when we move them.
- What is the runtime?
- This is a little trickier, since the loop kind of starts over again and again
- But if we think about it in the worst possible case…
- We would find an inversion at
i == 0
- Then at
i == 1
- Then at
i == 2
… - And each time, we would have to look at
i + 1
items - Until
i = n
- We would find an inversion at
- It’s that sort of “triangular” behavior we saw before: again!
- You can also think of it like: each number in the array might need to move positions down, and there are numbers
- How many comparisons?
- Again, it’s gonna be
- Cause each of those numbers will have to move positions, requiring the same number of comparisons
Insertion sort
- Let’s (try to) do better.
- Insertion sort is a bit like a combination between selection and bubble sort.
- Like selection sort, we will have a “sorted part” of the array.
- Like bubble sort, we will “slide” items around.
- Here’s the algorithm:
- Pick the first item from the “unsorted” part of the array.
- Insert that item into the “sorted” part in the correct order.
-
We “slide” it into place right-to-left, kinda like bubble sort.
-
- Think of it like picking books off a shelf, and sliding them into place in the right order
- What is the runtime?
- It takes time to “slide” each number into place
- Therefore it’s still …
- Aaargh!!!
- How many comparisons?
- Again, for each item, since it might have to be compared to every item to its left
- So overall…
- Just as a brain teaser: how could we find where to put the item in the sorted part faster?
- We could use binary search
- That lets us find the right location in time…
- But it still takes time to move the items after it over. So we haven’t improved things significantly.
This is frustrating
- It feels like we should be able to do better, somehow.
- Well, we can.
- Next time we’ll look at three new sorting algorithms
- Two of them will be faster in general..
- And one will be faster in a totally different way!