中级实训

Set 10

1. Where is the isValid method specified? Which classes provide an implementation of this method?

specified : Grid
implementation: BoundedGrid and UnboundedGrid

//@file: framework/info/gridworld/grid/Grid.java
//@line: 50
    boolean isValid(Location loc);

//@file: 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();
    }

//@file: framework/info/gridworld/grid/UnboundedGrid.java
//@line: 53~56
    public boolean isValid(Location loc)
    {
        return true;
    }

2. Which AbstractGrid methods call the isValid method? Why don’t the other methods need to call it?

(1)getValidAdjacentLocations方法调用了isValid方法

//@file: framework/info/gridworld/grid/ AbstractGrid .java
//@line: 44
 if (isValid(neighborLoc))

(2)因为其他方法(getEmptyAdjacentLocations和getOccupiedAdjacentLocations)通过getValidAdjacentLocations方法间接使用了isVaild方法,所以无需直接调用isVaild方法

//@file: framework/info/gridworld/grid/ AbstractGrid .java
//@line: 54
for (Location neighborLoc : getValidAdjacentLocations(loc))

//@file: framework/info/gridworld/grid/ AbstractGrid .java
//@line: 65
for (Location neighborLoc : getValidAdjacentLocations(loc))

3.Which methods of the Grid interface are called in the getNeighbors method? Which classes provide implementations of these methods?

(1)getNeighbors方法调用了 get 和 getOccupiedAdjacentLocations方法。

//@file: framework/info/gridworld/grid/ AbstractGrid .java
//@line: 28~34
public ArrayList<E> getNeighbors(Location loc)
{
    ArrayList<E> neighbors = new ArrayList<E>();
    for (Location neighborLoc : getOccupiedAdjacentLocations(loc))
        neighbors.add(get(neighborLoc));
    return neighbors;
}

(2)
AbstractGrid 类实现了getOccupiedAdjacentLocations方法,

//@file: framework/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;
}

BoundedGrid and UnboundedGrid 类实现了get方法

//@file: 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: 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);
    }

4. 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?

get方法返回存储在给定位置的网格中的对象的引用,如果不存在对象,则返回null。getempty邻接位置调用get方法,并测试结果是否为空。如果返回null,则该位置为“空”,并添加到列表中。调用get方法是测试给定位置是否为空或已占用的惟一方法。

//@file: 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;
    }

//@file: framework/info/gridworld/grid/Grid.java
//@line: 72~79
/**
 * Returns the object at a given location in this grid. <br />
 * Precondition: <code>loc</code> is valid in this grid
 * @param loc a location in this grid
 * @return the object at location <code>loc</code> (or <code>null<code> 
 *  if the location is unoccupied)
 */
E get(Location loc);

5. 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?

如果附近的位置都是有效的,有效的邻近位置的数目将从8个减少到4个。
有效的相邻位置应该是给定位置的北、南、东、西。

如果将Location.HALF_RIGHT替换为Location.RIGHT值改变后的代码如下:

//@file: framework/info/gridworld/grid/Location.java
//@line:40
public static final int RIGHT = 90;

//@file: framework/info/gridworld/grid/Location.java
//@line: 48
public static final int HALF_RIGHT = 45;

//@file: framework/info/gridworld/grid/AbstractGrid.java
//@line: 36~49
public ArrayList<Location> getValidAdjacentLocations(Location loc)
 {
        ArrayList<Location> locs = new ArrayList<Location>();

    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.RIGHT;
    }
    return locs;
}

Set 11

1. What ensures that a grid has at least one valid location?

如果rows <= 0或cols <= 0,BoundedGrid的构造函数 BoundedGrid(int rows, int cols)将抛出IllegalArgumentException。

//@file: 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];
    }

2. How is the number of columns in the grid determined by the getNumCols method? What assumption about the grid makes this possible?

(1)occupantArray[0].length

//@file: 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;
}

(2)getNumCols返回占有者数组第0行中的列数。构造函数确保每个有界网格对象至少有一行和一列。

//@file: 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];
    }

3.What are the requirements for a Location to be valid in a BoundedGrid?

Location 的行数必须大于或等于0且小于BoundedGrid的行数。Location的列数必须大于或等于0,并且小于BoundedGrid的列数。

//@file: 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.

1. What type is returned by the getOccupiedLocations method? What is the time complexity (Big-Oh) for this method?

(1) 返回值类型为ArrayList

(2) 时间复杂度:O(r*c)

//@file: 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;

}

2. What type is returned by the get method? What parameter is needed? What is the time complexity (Big-Oh) for this method?

(1)返回值类型:E
(2)需要的参数:一个Location对象
(3)时间复杂度: O(1)

 //@file: 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
    }

3. What conditions may cause an exception to be thrown by the put method? What is the time complexity (Big-Oh) for this method?

(1)

  1. 如果要添加的对象的Location不在网gird中(无效Location),则
    抛出IllegalArgumentException。
  2. 如果传递给put方法的对象为null,则抛出NullPointerException。

(2)时间复杂度: O(1)

//@file: 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;
    }

4. 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?

(1)返回值类型:E
(2)没有异常发生,因为该方法一律将grid的loc处设为null。
(3)时间复杂度:O(1)

//@file: 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;
    }

5. Based on the answers to questions 4, 5, 6, and 7, would you consider this an efficient implementation? Justify your answer.

是。
除了getOccupiedLocations方法的时间复杂度为O(r * c)外,其他方法的时间复杂度均为O(1).
改进的方法:使用一个链表(或者使用 HashMap<Location, E>)存储occupiedLocations,那么可以将时间复杂度降为O(n),n为occupiedLocations的数目。

Set 12

1. 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?

(1)Location类必须实现hashCode和equals方法。

//@file: framework/info/gridworld/grid/Location.java
//@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();
}

//@file: framework/info/gridworld/grid/Location.java
//@line: 218~221
public int hashCode()
{
    return getRow() * 3737 + getCol();
}

(2)Location类需要实现compareTo方法

//@file: framework/info/gridworld/grid/Location.java
//@line: 234~246
    public int compareTo(Object other)
    {
        Location otherLoc = (Location) other;
        if (getRow() < otherLoc.getRow())
            return -1;
        if (getRow() > otherLoc.getRow())
            return 1;
        if (getCol() < otherLoc.getCol())
            return -1;
        if (getCol() > otherLoc.getCol())
            return 1;
        return 0;
    }

(3) Location类满足所有这些需求。

2. 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?

//@file: 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();
    }

3. 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?

4. How would the behavior of this class differ, aside from time complexity, if a TreeMap were used instead of a HashMap?

5. 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实现。
优点之一是,我们可以节省更多的内存使用二维数组的实现。
因为我们应该只存储对象,而散列映射应该存储位置和对象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章