参考:数据结构与算法分析——Java语言描述 (美)Mark Allen Weis
基本上参考书上的代码,算是一个比较完全的单链表(带头结点)的实现吧。用了三个类来实现,一个类是链表本身LinkList,其中节点类ListNode作为它的内部类,是第二个类。第三个类代表位置LinkListItr。
LinkList:
/**
* 链表类
*/
package com.test;
public class LinkList {
ListNode header;
LinkListItr itr;
public LinkList(){
header=new ListNode(null);
}
//返回头结点的位置
public LinkListItr zeroth(){
return new LinkListItr(header);
}
//返回第一个节点的位置
public LinkListItr first(){
return new LinkListItr(header.next);
}
//插入元素
public void insert(Object x,LinkListItr p){
p.current.next=new ListNode(x,p.current.next);
}
// findprevious
public LinkListItr findPrevious(Object x){
LinkListItr p=zeroth();
while(p.current.next!=null && !p.current.next.element.equals(x))
p.advance();
return p;
}
//删除
public void remove(Object x){
LinkListItr p=findPrevious(x);
if(p.current.next!=null)
p.current.next=p.current.next.next;
}
//打印链表
public void print(){
LinkListItr p=first();
while(p.current!=null)
{
System.out.print(p.retrieve()+" << ");
p.advance();
}
System.out.println();
}
//反转并输出
public void reverse(){
//找到最后一个节点
LinkListItr last=first();
while(last.current.next!=null)
last.advance();
//System.out.println(last.current.element);
if(header.next!=null && header.next.next!=null)
{
ListNode f=header.next;
ListNode s=header.next.next;
header.next=last.current;
while(f!=s && s!=null)
{
ListNode tmp=null;
if(s.next!=null)
tmp=s.next;
s.next=f;
if(f.next==s)
f.next=null;
f=s;
s=tmp;
}
}
print();
System.out.println();
}
}
//节点类
class ListNode{
ListNode(Object theElement){
element=theElement;
next=null;
}
ListNode(Object theElement,ListNode next){
element=theElement;
this.next=next;
}
Object element;
ListNode next;
}
LinkListItr:
/**
* 链表位置
*/
package com.test;
public class LinkListItr {
public LinkListItr(ListNode c) {
current=c;
}
//返回当前位置上的元素
public Object retrieve(){
return current==null? null:current.element;
}
//向前移动一步
public void advance(){
if(current!=null)
current=current.next;
}
//是否超过最后一个元素
public boolean isPastEnd(){
return current==null;
}
ListNode current;
}
Main:
package com.test;
public class Main {
public static void main(String[] args) {
LinkList l1=new LinkList();
l1.insert(34,l1.zeroth());
System.out.println("链表l1:");
l1.print();
System.out.println("链表l1反转后:");
l1.reverse();
LinkList l2=new LinkList();
l2.insert(34,l2.zeroth());
l2.insert(10,l2.zeroth());
l2.insert(24,l2.zeroth());
l2.insert(8,l2.zeroth());
l2.insert(96,l2.zeroth());
System.out.println("链表l2:");
l2.print();
System.out.println("链表l2删除节点10:");
l2.remove(10);
l2.print();
System.out.println("链表l2反转后:");
l2.reverse();
}
}
这里,解释一下反转单链表的思路:
头结点是一个特殊的节点,反转之后仍然让它作为第一个节点而存在。
(1)首先,找到最后一个节点。
(2)让指针 f 指向第一个节点,即 header.next ,让s指向第二个节点,即 header.next.next 。然后,头结点的 next 指向最后一个节点。
(3)让指针 tmp 指向s.next , 然后 s.next=f ,f 改为指向 s ,s 改为指向 tmp 。 注意之前有这个判断:
if(f.next==s)
f.next=null;
如果没有这个判断的话,最终,最后的两个节点会形成一个回路。
第三步不断重复即可,注意终止条件。可以想象,如果原链表只有头结点或只有头结点和一个节点,那么,反转它和没有反转是一样的。
Main 的运行结果:
链表l1:
34 <<
链表l1反转后:
34 <<
链表l2:
96 << 8 << 24 << 10 << 34 <<
链表l2删除节点10:
96 << 8 << 24 << 34 <<
链表l2反转后:
34 << 24 << 8 << 96 <<