CS61B :链表(IntList,SLList....)

本文介绍了如何使用Java实现链表结构,包括SLList类和IntNode节点类。SLList用于用户交互,通过IntNode封装裸递归结构。讨论了方法的破坏性与非破坏性,如`addFirst`、`getFirst`,并提出使用哨兵节点解决空链表操作的复杂性。此外,文章还提及了泛型列表的概念,使得链表可以适应多种类型的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表(IntList,SLList…)

  1. If the main method in one java file not exists or incomplete, idea have no optons for run the program.
  2. We need two classes, one is the naked recursion IntNode, the other is SLList class to cover the naked one, making it more convenient and clear for users to use it.
  3. SLList is for interactive with users. The key is it construct an IntNode object using the IntNode class, like clothes wrap the whole naked recursion structure.
    : In the past, we have to construct Intlist:
IntNode first = new IntNode(5,null);

SLList:

SLList first = new SLList(5);

Below is the IntNode class

public class IntNode {
    public int item;
    public IntNode next;
    public IntNode(int f,IntNode r){
        first = f;
        rest = r;
    }
}
Here is the SLList class:
public class SLList {
    private IntNode first;/*prevent other class directly access the naked data sturcture, we nee private to prevent.ould be only accessed within the same class.*/
    public SLList(int x){
        first = new IntNode(x,null);
    }
   
    public static void main(){
        SLList L = new SLList(1);

    }
}

Methods:

  1. addFirst
 public void addFirst(int x){
        first = new IntNode(x,first);
    }
  1. getFirst
public int getFirst(){
  return first.item
  }
  1. size:
    When I use first as an IntNode variable to run the method, I find this method is destructive, which means the original list will be changed.
    The method shown below:
public int size(){
 int size = 1;
 for(int n = 0; n >= 0;n++){
 if(first.next! = null){
 size++;
 first=first.next;
 }
 else{
  return size;
  }
  }return size;
  }

Instead, we can refer an IntNode p as an variable to escape the destruction. this is called non-destructive

public int size(IntNode p){
   if(p.next == null){
   return 1;
   }else{
   return size(p.next)+1;
   }
   }
public int Size(){
 return size(first)

addLast:

  1. p=p.next 不会改变first,但是p=new会改变first,前者只是address一样,所以只是p=p.next都是first内部的,所以不会改变p,为什么p.next=new IntNode(x,null) 会改变first呢:
IntNode L1 =new IntNode(2,null);
L1 = new IntNode(4,L1);
IntNode L2 = L1;
L2 = L1.next;/*只改指针,不改内容,因为相当于reference type赋值,只是更改了address*/
L2.item = 3; /*会改变L1与L2,因为是reference type, reference type会改变二者,primitive type不会*/
L2.next = new IntNode(5,null)/*会改变L1和L2,因为是给L2.next创建了一个address并指向里面*/

size improvement
Obviously, the size() method is unefficient, so we will add a integer variable to track the size of the list.

private int size;

public SLList (int x) {
    size = 1;
    ...
}

public void addFirst(int x) {
    size += 1;
    ...
}

public void addLast (int x) {
    size += 1;
    ...
}

public int size() {
    return size;
}

parameter passing: copy the bits of those variables into the parameters variables.
golden rule of equals (GroE) : when we assign a value with equals, we are just copying the bits from one memory box to another!

Nested class

public class SLList {
   /*here is the nested class*/private static class IntNode {
            public int item;
            public IntNode next;
            public IntNode(int i, IntNode n) {
                item = i;
                next = n;
            }
       }

       private IntNode first; 

       public SLList(int x) {
           first = new IntNode(x, null);
       } 
...

nested class is for clear and organized. has no practical meannings.
Besides, nested class should be static, so that it can not access the variables and instance in SLList class.

因为empty list没有.next,所以如果以empty list开头,很多方法就会变得很复杂,so we need a object called sentinal node to tackle the issue.

  1. change first in sentinel
/** The first item, if it exists, is at sentinel.next. */
private IntNode sentinel;

public SLList() {
    sentinel = new IntNode(63, null);
    size = 0;
}

public SLList(int x) {
    sentinel = new IntNode(63, null);
    sentinel.next = new IntNode(x, null);
    size = 1;
}

public void addFirst(int x) {
    sentinel.next = new IntNode(x, sentinel.next);
    size = size + 1;
}

public int getFirst() {
    return sentinel.item;
}

public void addLast(inx x) {
    IntNode p = sentinel;
    while (p.next != null) {
        p = p.next;
    }
    p.next = new IntNode(x, null);
    size = size + 1;
}

A SLList with a sentinel node has at least the following invariants:

The sentinel reference always points to a sentinel node. (the first node must be sentinel node)
The front item (if it exists), is always at sentinel.next.item.(first = sentinel.next)
The size variable is always the total number of items that have been added.

Generic List
We could improve our IntList to make it available for other types.

public class DLList<BleepBlorp> {
    private IntNode sentinel;
    private int size;

    public class IntNode {
        public IntNode prev;
        public BleepBlorp item;
        public IntNode next;
        ...
    }
    ...
}

We put the desired type inside of angle brackets during declaration, and also use empty angle brackets during instantiation.

DLList d2 = new DLList<>(“hello”);
d2.addLast(“world”);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值