实现链表的时候,一个很实用的实践是在链表前面加一个不储存数据的“头节点”。

如上图,头节点不储存数据。从头节点的后一个元素开始才是链表的第一个元素。当链表为空的时候,链表只有一个头节点,而且next指针为空。
头节点作为经典设计,好处很明显:
3种不同的方法实现“单向链表”:
版本1. 只有头节点:head。

版本2. 有一个头节点head,一个尾节点tail。

版本3. 没有头节点,没有尾节点。只有普通节点。

JDK里的官方LinkedList是没有头节点的版本。但实现写得不繁琐。
参见《JDK1.8源码分析之LinkedList》这篇文章。
根据《Think in Java》书中练习的要求,所有增删修改的方法都没有在链表本体里,而是放在Iterator的下面。
package com.ciaoshen.thinkinjava.chapter17;
import java.util.*;
@SuppressWarnings(value={"unchecked", "rawtypes"})
public class SListV2<T>{
private Node<T> head;
private Node<T> tail;
private int size=0;
public SListV2(){
head=new Node();
tail=head;
}
private static class Node<T>{
private T item;
private Node<T> next;
public Node(){item=null;next=null;}
public Node(T t){item=t;next=null;}
public String toString(){return item.toString();}
}
private class SListIterator{
private Node<T> cursor=head;
private Node<T> previous=cursor;
private int index=0;
//在cursor后面插入新元素
public void add(T t){
Node<T> n=new Node<T>(t);
n.next=tail.next;
tail.next=n;
tail=n;
size++;
}
//替换cursor位置元素
public void set(T t){
if(cursor==head){
System.out.println("Not Begun!");
}else{
Node<T> n=new Node<T>(t);
cursor.item=t;
}
}
//从cursor位置开始往后删除
public void remove(){
if(cursor==previous){
System.out.println("Can't remove!");
}else{
if(cursor==tail){
tail=previous;
}
previous.next=cursor.next;
cursor=previous;
index--;
size--;
}
}
//current还没到tail
public boolean hasNext(){
return cursor.next!=null;
}
//返回cursor的下一个元素
public Node<T> next(){
if(hasNext()){
previous=cursor;
cursor=cursor.next;
index++;
return cursor;
}else{
System.out.println("Reach the end!");
return null;
}
}
public int index(){
return index;
}
public int size(){
return size;
}
public void reset(){
cursor=head;
previous=cursor;
index=0;
}
}
public SListIterator iterator(){
return new SListIterator();
}
public String toString(){
StringBuilder sb=new StringBuilder();
SListIterator ite=iterator();
while(ite.hasNext()){
sb.append("["+ite.next()+"]");
if(ite.hasNext()){
sb.append(",");
}
}
return sb.toString();
}
/**
* 测试
*/
public static void main(String[] args){
String[] s="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z".split(" ");
SListV2<String> list=new SListV2<String>();
SListV2.SListIterator ite=list.iterator();
for(int i=0;i<s.length;i++){
ite.add(s[i]);
}
System.out.println(list);
for(int i=0;i<ite.size();i++){
System.out.println(ite.next());
}
ite.reset();
int length=ite.size();
for(int i=0;i<10;i++){
Node<String> n=ite.next();
ite.remove();
ite.remove();
}
System.out.println(list);
}
}
@SuppressWarnings(value={“unchecked”, “rawtypes”})
public class SListV3
private Node<T> head;
private Node<T> tail;
private int size=0;
public SListV3(){
head=new Node();
tail=new Node();
head.next=tail;
tail.next=head;
}
private static class Node<T>{
private T item;
private Node<T> next;
public Node(){item=null;next=null;}
public Node(T t){item=t;next=null;}
public String toString(){return item.toString();}
}
private class SListIterator{
private Node<T> cursor=head;
private Node<T> previous=cursor;
private int index=0;
//在tail栓塞前插入新元素
public void add(T t){
Node<T> n=new Node<T>(t);
tail.next.next=n;
n.next=tail;
tail.next=n;
size++;
}
//替换当前cursor元素(若当前元素被删,也不能set。)
public void set(T t){
if(cursor==previous){
System.out.println("Cannot set!");
}else{
cursor.item=t;
}
}
//只删除上一次next()返回的元素。每次next()只能删除一次。
public void remove(){
if(cursor==previous){
System.out.println("Can't remove!");
}else{
if(tail.next==cursor){
tail.next=previous;
}
previous.next=cursor.next;
cursor=previous;
index--;
size--;
}
}
//current还没到tail
public boolean hasNext(){
return cursor.next!=tail;
}
//返回cursor的下一个元素
public Node<T> next(){
if(hasNext()){
previous=cursor;
cursor=cursor.next;
index++;
return cursor;
}else{
System.out.println("Reach the end!");
return null;
}
}
public int index(){
return index;
}
public int size(){
return size;
}
public void reset(){
cursor=head;
previous=cursor;
index=0;
}
}
public SListIterator iterator(){
return new SListIterator();
}
public String toString(){
StringBuilder sb=new StringBuilder();
SListIterator ite=iterator();
while(ite.hasNext()){
sb.append("["+ite.next()+"]");
if(ite.hasNext()){
sb.append(",");
}
}
return sb.toString();
}
/**
* 测试
*/
public static void main(String[] args){
String[] s="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z".split(" ");
SListV3<String> list=new SListV3<String>();
SListV3.SListIterator ite=list.iterator();
for(int i=0;i<s.length;i++){
ite.add(s[i]);
}
System.out.println(list);
for(int i=0;i<ite.size();i++){
System.out.println(ite.next());
}
ite.reset();
int length=ite.size();
for(int i=0;i<10;i++){
Node<String> n=ite.next();
ite.remove();
ite.remove();
}
System.out.println(list);
} } ```
package com.ciaoshen.thinkinjava.chapter17;
import java.util.*;
@SuppressWarnings(value={"unchecked", "rawtypes"})
public class SListV4<T>{
private Node<T> head;
private Node<T> tail;
private int size=0;
public SListV4(){
head=new Node();
tail=head;
}
private static class Node<T>{
private T item;
private Node<T> next;
public Node(){item=null;next=null;}
public Node(T t){item=t;next=null;}
public Node(T t, Node<T> n){item=t;next=n;}
public String toString(){return item.toString();}
}
private class SListIterator{
private Node<T> cursor=null;
private Node<T> previous=null;
private int index=-1;
//在tail栓塞前插入新元素
public void add(T t){
//空链表
if(head.item==null){
head.item=t;
}else{
Node<T> n=new Node<T>(t);
tail.next=n;
tail=n;
}
size++;
}
//替换当前cursor元素(若当前元素被删,也不能set。)
public void set(T t){
if(cursor==previous){
System.out.println("Cannot set!");
}else{
cursor.item=t;
}
}
//只删除上一次next()返回的元素。每次next()只能删除一次。
public void remove(){
if(cursor==previous){
System.out.println("Can't remove!");
}else{
if(cursor==head){
cursor.item=null;
cursor=null;
} else {
previous.next=cursor.next;
cursor=previous;
}
index--;
size--;
}
}
//current还没到tail
public boolean hasNext(){
if(cursor==null){
return (head.item==null && head.next==null)? false:true;
}else{
return (cursor.next==null)? false:true;
}
}
//返回cursor的下一个元素
public Node<T> next(){
if(hasNext()){
if(cursor==null && head.item==null){
cursor=head.next;
previous=head;
}else if(cursor==null && head.item!=null){
cursor=head;
}else{
previous=cursor;
cursor=cursor.next;
}
index++;
return cursor;
}else{
System.out.println("Reach the end!");
return null;
}
}
public int index(){
return index;
}
public int size(){
return size;
}
public void reset(){
cursor=previous=null;
index=0;
}
}
public SListIterator iterator(){
return new SListIterator();
}
public String toString(){
StringBuilder sb=new StringBuilder();
SListIterator ite=iterator();
while(ite.hasNext()){
sb.append("["+ite.next()+"]");
if(ite.hasNext()){
sb.append(",");
}
}
return sb.toString();
}
/**
* 测试
*/
public static void main(String[] args){
String[] s="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z".split(" ");
SListV4<String> list=new SListV4<String>();
SListV4.SListIterator ite=list.iterator();
for(int i=0;i<s.length;i++){
ite.add(s[i]);
}
System.out.println(list);
for(int i=0;i<ite.size();i++){
System.out.println(ite.next());
}
ite.reset();
for(int i=0;i<10;i++){
Node<String> n=ite.next();
ite.set("XXX");
System.out.println(list);
ite.remove();
}
System.out.println(list);
}
}