关于单链表的一些实现

        参考:数据结构与算法分析——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   ,改为指向 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 <<

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值