Set 10
-
Where is the isValid method specified? Which classes provide an implementation of this method?
Answer:TheisValid
method is specified by Grid, and is implemented by the BounededGrid class and UnboundedGrid class.
Source code:// @file: GridWorldCode/framework/info/gridworld/grid/Grid.java // @line: 50 boolean isValid(Location loc); // @file: GridWorldCode/framework/info/gridworld/grid/UnboundedGrid.java // @line: 53~56 public boolean isValid(Location loc) { return true; } // @file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 60~64 public boolean isValid(Location loc) { return 0 <= loc.getRow() && loc.getRow() < getNumRows() && 0 <= loc.getCol() && loc.getCol() < getNumCols(); }
-
Which AbstractGrid methods call the isValid method? Why don’t the other methods need to call it?
Answer:getValidAdjacentLocations()
call the isValid method. Other methods likegetEmptyAdjacentLocations()
andgetOccupiedAdjacentLocations
,they callgetValidAdjacentLocations()
insteadly, More Examples likegetNeighbors ()
callgetOccupiedAdjacentLocations
to invokegetValidAdjacentLocations
. They callisValid()
indirectly.
Source code:// @file: GridWorldCode/framework/info/gridworld/grid/AbstractGrid.java // @line: 44~45 if (isValid(neighborLoc)) locs.add(neighborLoc);
-
Which methods of the Grid interface are called in the getNeighbors method? Which classes provide implementations of these methods?
Answer:getNeighbors()
调用了Grid 接口中的get()
和getOccupiedAdjacentLocations
method.
(1)get()
方法在 BoundedGrid类和UnboundedGrid类中实现。
(2)getOccupiedAdjacentLocations
方法在AbstractGrid类中实现。
Source code:// @file: GridWorldCode/framework/info/gridworld/grid/AbstractGrid.java // @line: 31~32 for (Location neighborLoc : getOccupiedAdjacentLocations(loc)) neighbors.add(get(neighborLoc)); // @file: info/gridworld/grid/AbstractGrid.java // @line: 62~71 public ArrayList<Location> getOccupiedAdjacentLocations(Location loc) { ArrayList<Location> locs = new ArrayList<Location>(); for (Location neighborLoc : getValidAdjacentLocations(loc)) { if (get(neighborLoc) != null) locs.add(neighborLoc); } return locs; } // @file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 85~91 public E get(Location loc) { if (!isValid(loc)) throw new IllegalArgumentException("Location " + loc + " is not valid"); return (E) occupantArray[loc.getRow()][loc.getCol()]; // unavoidable warning } // @file: GridWorldCode/framework/info/gridworld/grid/UnboundedGrid.java // @line: 66~71 public E get(Location loc) { if (loc == null) throw new NullPointerException("loc == null"); return occupantMap.get(loc); }
-
Why must the get method, which returns an object of type E, be used in the getEmptyAdjacentLocations method when this method returns locations, not objects of type E?
Answer:因为get
方法返回对存储在网格中给定位置的对象的引用,如果没有对啊ing则返回null,所以get
方法必须返回类型E的对象。getEmptyAdjacentLocations
方法使用get
方法来检测给定位置是否为空,不是空的则将该位置添加到列表中,只有这样我们才能的正确的空的相邻位置。
Source code:// @file: GridWorldCode.framework/info/gridworld/grid/AbstractGrid.java // @line: 51~60 public ArrayList<Location> getEmptyAdjacentLocations(Location loc) { ArrayList<Location> locs = new ArrayList<Location>(); for (Location neighborLoc : getValidAdjacentLocations(loc)) { if (get(neighborLoc) == null) locs.add(neighborLoc); } return locs; }
-
What would be the effect of replacing the constant Location.HALF_RIGHT with Location.RIGHT in the two places where it occurs in the getValidAdjacentLocations method?
Answer:如果用right代替half_right,那么可选择的方向将会减半,也就是从八个变成四个,东南西北。
Source code:// @file: GridWorldCode/framework/info/gridworld/grid/AbstractGrid.java // @line: 40~47 int d = Location.NORTH; for (int i = 0; i < Location.FULL_CIRCLE / Location.HALF_RIGHT; i++) { Location neighborLoc = loc.getAdjacentLocation(d); if (isValid(neighborLoc)) locs.add(neighborLoc); d = d + Location.HALF_RIGHT; }
Set 11
-
What ensures that a grid has at least one valid location?
答:BoundedGrid类的构造函数规定:如果grid的行数或者列数小于或等于0就会抛出异常,这确保了grid中至少有一个有效位置。
source code://@file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java //@line: 39~46 public BoundedGrid(int rows, int cols) { if (rows <= 0) throw new IllegalArgumentException("rows <= 0"); if (cols <= 0) throw new IllegalArgumentException("cols <= 0"); occupantArray = new Object[rows][cols]; }
-
How is the number of columns in the grid determined by the getNumCols method? What assumption about the grid makes this possible?
答:因为BoundedGrid是用一个二维数组还储存的,所以调取该二维数组并查询任意一行的长度即可直到grid的列数。
Grid要求行数和列数至少为一使之成为可能。
Source Code:// @file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 53~58 public int getNumCols() { // Note: according to the constructor precondition, numRows() > 0, so // theGrid[0] is non-null. return occupantArray[0].length; }
-
What are the requirements for a Location to be valid in a BoundedGrid?
答:该 Location所在的行数大于等于0且小于grid的总行数;该 Location所在的列数大于等于0且小于grid的总列数;
Source Code://@file: GridWroldCode/framework/info/gridworld/grid/BoundedGrid.java //@line: 60~64 public boolean isValid(Location loc) { return 0 <= loc.getRow() && loc.getRow() < getNumRows() && 0 <= loc.getCol() && loc.getCol() < getNumCols(); }
In the next four questions, let r = number of rows, c = number of columns, and n = number of occupied locations.
-
What type is returned by the getOccupiedLocations method? What is the time complexity (Big-Oh) for this method?
答:getOccupiedLocations()
方法返回的类型是ArrayList<Location>
因为要得到所有被占用的的位置必须扫描整个网格,所以时间复杂度为O(r*c)
Source code:// @file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 66~83 public ArrayList<Location> getOccupiedLocations() { ArrayList<Location> theLocations = new ArrayList<Location>(); // Look at all grid locations. for (int r = 0; r < getNumRows(); r++) { for (int c = 0; c < getNumCols(); c++) { // If there's an object at this location, put it in the array. Location loc = new Location(r, c); if (get(loc) != null) theLocations.add(loc); } } return theLocations; }
-
What type is returned by the get method? What parameter is needed? What is the time complexity (Big-Oh) for this method?
答:get()
方法返回的类型为E;需要一个Location对象作为参数;复杂度:O(1)
Source Code:// @file: GridWrodlCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 85~91 public E get(Location loc) { if (!isValid(loc)) throw new IllegalArgumentException("Location " + loc + " is not valid"); return (E) occupantArray[loc.getRow()][loc.getCol()]; // unavoidable warning }
-
What conditions may cause an exception to be thrown by the put method? What is the time complexity (Big-Oh) for this method?
答:当要添加对象的location不在网格内的时候会抛出异常:IllegalArgumentException
.
当要添加的对象是null的话会抛出异常:NullPointerException
.
时间复杂度为:O(1)
Source Code// @file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 93~105 public E put(Location loc, E obj) { if (!isValid(loc)) throw new IllegalArgumentException("Location " + loc + " is not valid"); if (obj == null) throw new NullPointerException("obj == null"); // Add the object to the grid. E oldOccupant = get(loc); occupantArray[loc.getRow()][loc.getCol()] = obj; return oldOccupant; }
-
What type is returned by the remove method? What happens when an attempt is made to remove an item from an empty location? What is the time complexity (Big-Oh) for this method?
答:remove
方法返回类型是 E,E可以实类中实际存储的任何对象类型。
如果该位置在网格内的话并不会报错,如果该位置不在网格内的话就会抛出异常。
时间复杂度为:O(1)
Source Code:// @file: GridWorldCode/framework/info/gridworld/grid/BoundedGrid.java // @line: 107~117 public E remove(Location loc) { if (!isValid(loc)) throw new IllegalArgumentException("Location " + loc + " is not valid"); // Remove the object from the grid. E r = get(loc); occupantArray[loc.getRow()][loc.getCol()] = null; return r; }
-
Based on the answers to questions 4, 5, 6, and 7, would you consider this an efficient implementation? Justify your answer.
答:答:我认为这个实现只能算是一个比较好的实现方式,虽然put
和get
和remove
的时间复杂度都是O(1),但是getOccupiedLocations
方法的复杂度去到了O(r*c),或许可以使用一些数据结构来存储网格使得该方法的时间复杂度降低。
Set 12
-
Which method must the Location class implement so that an instance of HashMap can be used for the map? What would be required of the Location class if a TreeMap were used instead? Does Location satisfy these requirements?
答:Location
类必须实现:hashCode
和equals
方法。
Location类实现了Comparable
接口,所以Location类还必须实现compareTo
。此外,TreeMap还要求映射的键是支持相互比较的。
是的,Location类满足所有要求。
Source Code:// @file: GridWorldCode/framework/info/gridworld/grid/Location.java // @line: 28 public class Location implements Comparable // @line: 218~221 public int hashCode() { return getRow() * 3737 + getCol(); } // @line: 205~212 public boolean equals(Object other) { if (!(other instanceof Location)) return false; Location otherLoc = (Location) other; return getRow() == otherLoc.getRow() && getCol() == otherLoc.getCol(); }
-
Why are the checks for null included in the get, put, and remove methods? Why are no such checks included in the corresponding methods for the BoundedGrid?
答:因为在UnboundedGrid中,数据存储在HashMap数据结构中,而且任何一个位置在UnbouGrid中都是valid,然而在Map对象中null是合法的键值这与UnboundedGrid中的键值约束冲突,所以在get
和put
和remove
方法中都得检查以下参数位置是否为空,空则抛出异常。
在BoundedGrid中,数据存储在二维数组中。在使用位置访问BoundedGrid中的occupantArray
方法之前都会先调用isValid
方法,一旦位置是null就会直接产生异常,所以在编写其他get
和put
和remove
方法时并不需要重复实现。 -
What is the average time complexity (Big-Oh) for the three methods: get, put, and remove? What would it be if a TreeMap were used instead of a HashMap?
答:get
和put
和remove
方法的平均时间复杂度时O(1)
如果使用TreeMap而不是HashMap的话,平均时间复杂度将会提升到O(log n)(n为网格中被占有的的location数量) -
How would the behavior of this class differ, aside from time complexity, if a TreeMap were used instead of a HashMap?
答:因为存储结构的改变会导致返回的对象列表顺序发生变化。存储结构的的变化还会导致数据访问方式的变化。 -
Could a map implementation be used for a bounded grid? What advantage, if any, would the two-dimensional array implementation that is used by the BoundedGrid class have over a map implementation?
答:map可以用来实现bounded grid。
相比于使用map实现,使用二维数组实现的优势:在Bounded grid中如果存储的数据对象很多,几乎占满了整个Bounded Grid的话,使用二维空间会更省内存。因为使用Map不仅要存储数据元素还要存储元素的位置,而二维数组只存储数据元素。
Codeing Exercises Questions
Question 2
These methods could be used without change:
public ArrayList<Location> getOccupiedLocations()
public E get(Location loc)
public E put(Location loc, E obj)
public E remove(Location loc)
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 version | LinkedList<OccupantInCol> version | HashMap version | TreeMap version |
---|---|---|---|---|
getNeighbors | O(c) | O(c) | O(1) | O(logn) |
getEmptyAdjacentLocations | O(c) | O(c) | O(1) | O(logn) |
getOccupiedAdjacentLocations | O(c) | O(c) | O(1) | O(logn) |
getOccupiedLocations | O(c+n) | O(r+n) | O(n) | O(n) |
get | O(c) | O(c) | O(1) | O(logn) |
put | O(c) | O(c) | O(1) | O(logn) |
remove | O(c) | O(c) | O(1) | O(logn) |
Question 3
- the Big-Oh efficiency of the
get
method is :O(1)
- the efficiency of the put method when the row and column index values are within the current array bounds is
O(1)
- the efficiency when the array needs to be resized :
O(n^2)
, n is the size of the array