[关闭]
@w1024020103 2017-02-06T16:27:48.000000Z 字数 2813 阅读 407

week2 2.2 notes

cs61b ucberkeley JoshHug


2.2 Lectures include SLLists, Nested Classes, Sentinel Nodes

Adding addLast(int x) and size() methods to SLList.java

implement the addLast method iteratively, though you could also do it recursively. The idea is fairly straightforward, we create a pointer variable p and have it iterate through the list to the end.

  1. /** Adds an item to the end of the list. */
  2. public void addLast(int x) {
  3. IntNode p = first;
  4. /* Advance p to the end of the list. */
  5. while (p.next != null) {
  6. p = p.next;
  7. }
  8. p.next = new IntNode(x, null);
  9. }

a recursive implementation of size is especially encouraged.

  1. private static int size(IntNode p){
  2. if (p.next = null){
  3. return 1;
  4. }
  5. return size(p.next) + 1;
  6. }
  7. public int size(){
  8. return size(first);
  9. }

Try to get to be familiar with recursive and iterative inplementation.

Having a size method that is very slow for large lists is unacceptable, since we can do better.It is possible to rewrite size so that it takes the same amount of time, no matter how large the list.To do so, we can simply add a size variable to the SLList class that tracks the current size, yielding the code below. This practice of saving important data to speed up retrieval is sometimes known as caching.

  1. public class SLList {
  2. private IntNode first;
  3. private int size;
  4. public SLList(int x) {
  5. first = new IntNode(x, null);
  6. }
  7. public void addFirst(int x){
  8. first = new IntNode(x,first);
  9. size += 1;
  10. }
  11. public int getFirst(){
  12. return first.item;
  13. }
  14. public void addLast(int x){
  15. size += 1;
  16. IntNode p = first;
  17. while(p.next != null){
  18. p = p.next;
  19. }
  20. p.next = new IntNode(x, null);
  21. }
  22. public int size(){
  23. return size;
  24. }
  25. }

Sentinel Nodes

Unfortunately, this causes our addLast method to crash if we insert into an empty list. Since first is null, the attempt to access p.next in while (p.next != null) below causes a null pointer exception.
One solution to fix addLast is to create a special case for the empty list, as shown below:

  1. public void addLast(int x) {
  2. size += 1;
  3. if (first == null) {
  4. first = new IntNode(x, null);
  5. return;
  6. }
  7. IntNode p = first;
  8. while (p.next != null) {
  9. p = p.next;
  10. }
  11. p.next = new IntNode(x, null);
  12. }

This solution works, but special case code like that shown above should be avoided when necessary. Human beings only have so much working memory, and thus we want to keep complexity under control wherever possible. For a simple data structure like the SLList, the number of special cases is small. More complicated data structures like trees can get much, much uglier.

A cleaner, though less obvious solution, is to make it so that all SLLists are the "same", even if they are empty. We can do this by creating a special node that is always there, which we will call a sentinel node. The sentinel node will hold a value, which we won't care about.

For example, the empty list created by SList L = new SList() would be as shown below:
empty_sentinelized_SLList.png-11.4kB

And an SLList with the items 5, 10, and 15 would look like:
three_item_sentenlized_SLList.png

In the figures above, the lavender ?? value indicates that we don't care what value is there. Since Java does not allow us to fill in an integer with question marks, we just pick some abitrary value like -518273 or 63 or anything else.
Since an SSList without a sentinel has no special cases, we can simply delete the special case from our addLast method, yielding:

  1. public void addLast(int x) {
  2. size += 1;
  3. IntNode p = sentinel;
  4. while (p.next != null) {
  5. p = p.next;
  6. }
  7. p.next = new IntNode(x, null);
  8. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注