链表(IntList,SLList…)
- If the main method in one java file not exists or incomplete, idea have no optons for run the program.
- 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.
- 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:
- addFirst
public void addFirst(int x){
first = new IntNode(x,first);
}
- getFirst
public int getFirst(){
return first.item
}
- 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:
- 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.
- 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”);