文件结构
.
├── 1
│ └── OccupantInCol.java
│ └── SparseBoundedGrid.java
│ └── SparseGridRunner.java
├── 2
│ └── SparseBoundedGrid2.java
│ └── SparseBoundedGrid3.java
│ └── SparseGridRunner.java
├── 3
│ └── UnboundedGrid2.java
│ └── SparseGridRunner.java
├── README.md
Coding Exercises
-
Suppose that a program requires a very large bounded grid that contains very few objects and that the program frequently calls the getOccupiedLocations method (as, for example, ActorWorld). Create a class SparseBoundedGrid that uses a “sparse array” implementation. Your solution need not be a generic class; you may simply store occupants of type Object.
The “sparse array” is an array list of linked lists. Each linked list entry holds both a grid occupant and a column index. Each entry in the array list is a linked list or is null if that row is empty.
You may choose to implement the linked list in one of two ways. You can use raw list nodes.
public class SparseGridNode { private Object occupant; private int col; private SparseGridNode next; ... ... }
Or you can use a LinkedList with a helper class.
public class OccupantInCol { private Object occupant; private int col; ... ... }
For a grid with r rows and c columns, the sparse array has length r. Each of the linked lists has maximum length c.
Implement the methods specified by the Grid interface using this data structure. Why is this a more time-efficient implementation than BoundedGrid?
前者的时间复杂度为O(r+n)(行数+占用位置数),后者的时间复杂度为O(r*c)(行数×列数)。The World has a public addGridClass method. Since the ActorWorld is a World, you can call this method in a runner. Here is the code to add a new grid to the GUI.
import info.gridworld.actor.Actor; import info.gridworld.actor.ActorWorld; import info.gridworld.grid.Location; import info.gridworld.actor.Critter; import info.gridworld.actor.Rock; import info.gridworld.actor.Flower; /** * This class runs a world with additional grid choices. */ public class SparseGridRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(); world.addGridClass("SparseBoundedGrid"); world.addGridClass("SparseBoundedGrid2"); world.addGridClass("SparseBoundedGrid3"); world.addGridClass("UnboundedGrid2"); world.add(new Location(2, 2), new Critter()); world.show(); } }
Note that you should firstly compile the SparseBoundedGrid.java to generate the SparseBoundedGrid.class.
When you execute a runner class and choose the World menu->set grid, the new grid type will be available for you to choose.
-
Consider using a
HashMap
orTreeMap
to implement theSparseBoundedGrid
. How could you use the UnboundedGrid class to accomplish this task? Which methods ofUnboundedGrid
could be used without change?
UnboudedGrid类中的大部分代码都可以直接用来实现SparseBoundedGrid类。
getOccupiedLocations()
函数不需要改变。Fill in the following chart to compare the expected Big-Oh efficiencies for each implementation of the
SparseBoundedGrid
.Let r = number of rows, c = number of columns, and n = number of occupied locations
Methods SparseGridNode
versionLinkedList<OccupantInCol>
versionHashMap
versionTreeMap
versiongetNeighbors
O( c ) O( c ) O( 1 ) O(log n) getEmptyAdjacentLocations
O( c ) O( c ) O( 1 ) O(log n) getOccupiedAdjacentLocations
O( c ) O( c ) O( 1 ) O(log n) getOccupiedLocations
O(r + n) O(r + n) O( n ) O( n ) get
O( c ) O( c ) O( 1 ) O(log n) put
O( c ) O( c ) O( 1 ) O(log n) remove
O( c ) O( c ) O( 1 ) O(log n) -
Consider an implementation of an unbounded grid in which all valid locations have non-negative row and column values. The constructor allocates a 16 x 16 array. When a call is made to the put method with a row or column index that is outside the current array bounds, double both array bounds until they are large enough, construct a new square array with those bounds, and place the existing occupants into the new array.
Implement the methods specified by the Grid interface using this data structure. What is the Big-Oh efficiency of the get method? What is the efficiency of the put method when the row and column index values are within the current array bounds? What is the efficiency when the array needs to be resized?
get()
时间复杂度:O(1)
put()
时间复杂度:当行和列的索引都在边界值内时是O(1),当超过时是O(n*n)(n是新数组的大小)。