使用迭代器(Iterator)来实现链表的相关操作

在这一篇里,要讲的是如何使用迭代器对链表进行相关的操作,比如删除,获取,插入等操作,那首先介绍一下什么是迭代器,java里面的迭代器的实用性很大,在我们实际对链表进行删除操作时,如果是要对某个限制条件下的所有链表数据都删除,如果是用普通的指针,那就必须每次都对链表进行遍历查找,符合了条件进行删除,而效率很低,而不像数组,有固定的下标位,所以我们设法给予一个类似数组下标的东西来表明链表的位置。

这时我们使用了一种类,叫迭代器类,迭代器类包含对数据结构的数据项的引用,并用来遍历这些结构的对象。

好了,大概介绍了一下,我们来看看迭代器的具体使用吧:

这里笔者用迭代器去代替一些链表操作,也就是这些操作可以在链表里执行的,但是放在迭代器里能更加明白其用法,首先创建一个链表:

<span style="font-size:18px;">public class Link {
	private long dData;
	private Link next;
	
	public Link(long dd){
		dData = dd;
	}
	
	public void displayLink(){
		System.out.print(dData + "  ");
	}
}</span>
这里有long型的数据,也有next的引用,作为标识下个链节点的引用,然后我们来创建链表:

<span style="font-size:18px;">public class LinkList {

	private Link first;
	
	public LinkList(){
		first = null;                         //构造函数初始化首节点
	}
	
	public Link getFirst() {                 //获取第一个节点
		return first;
	}

	public void setFirst(Link first) {        //设置第一个节点
		this.first = first;
	}
	
	public boolean isEmpty(){                //判断链表是否为空
		return (first == null);
	}
	
	public LinkIterator myIterator(){        //定义迭代器,与之联系起来
		return new LinkIterator(this);
	}
	
	public void displayLinklist(){          //打印出链表中的元素
		Link current = first;
		while (current != null) {
			System.out.print(current.dData + "   ");
			current = current.next;
		}
		System.out.println("");
	}
}</span>

其他函数没什么好说的,主要要注意一下关于链表和迭代器之间的联系,在链表中创建迭代器时,传递给迭代器一个引用,这个引用储存在迭代器的一个字段中,这样迭代器就可以访问链表中的私有数据字段了。

然后是迭代器类的实现:

public class LinkIterator {
	private Link current;
	private Link previous;
	private LinkList outlist;
	
	public LinkIterator(LinkList mLinkList){                  //构造函数,同时进行将迭代器置于表头
		outlist = mLinkList;
		reset();
	}
	
	public void reset(){									//将迭代器置于表头方法
		current = outlist.getFirst();
		previous = null;
	}
	
	public boolean atEnd(){                              //判断迭代器是否位置在表尾
		return (current.next == null);
	}
	
	public void nextLink(){                             //将迭代器的位置向后移动一位
		previous = current;
		current = current.next;
	}
	
	public Link getCurrent(){                           //返回此时迭代器所指链节点的值
		return current;
	}
	
	public void inserAfter(long dd){                   //插入迭代器所指链节点的后面
		Link newLink = new Link(dd);
		if (outlist.isEmpty()) {
			outlist.setFirst(newLink);
			current = newLink;
		}
		else {
			newLink.next = current.next;
			current.next = newLink;
			nextLink();
		}
	}
	
	public void insertBefore(long dd){                   //插入迭代器所指链节点对的前面
		Link newlink = new Link(dd);
		
		if (previous == null) {
			newlink.next = outlist.getFirst();
			outlist.setFirst(newlink);
			reset();
		}else {
			newlink.next = previous.next;
			previous.next = newlink;
			current = newlink;
		}
	}
	
	public long deleteLink(){                            //删除迭代器所指的链节点
		long data = current.dData;
		
		if (previous == null) {
			outlist.setFirst(current.next);
			reset();
		}else {
			previous.next = current.next;
			if (atEnd()) {
				reset();
			}else {
				current = current.next;
			}
		}
		return data;
	}
}
这个迭代器类实现要注意节点直接的关系,注意判断节点的位置和表是否为空,这两点经常会忘记。然后就是主要函数的调用了,这里笔者分为几个操作进行功能的调用:

public class IteratorTest {
	
	public static void main(String[] args) throws IOException {
		LinkList mLinkList = new LinkList();
		LinkIterator mIterator = mLinkList.myIterator();
		
		long value;
		
		mIterator.inserAfter(20);
		mIterator.inserAfter(40);
		mIterator.inserAfter(80);
		mIterator.insertBefore(60);
		
		while (true) {
			System.out.println("please input the letter to operate the Iterator: ");
			System.out.println("you can input the word of s,r,g,n,b,a,d: ");
			System.out.flush();
			int m = getChar();
			
			switch (m) {
			case 's':
				if (!mLinkList.isEmpty()) {
					mLinkList.displayLinklist();
				}else {
					System.out.println("the linklist is empty");
				}
				break;
				
			case 'r':
				mIterator.reset();
				break;
				
			case 'g':
				if (!mLinkList.isEmpty()) {
					value = mIterator.getCurrent().dData;
					System.out.println("Return data is : " + value);
				}else {
					System.out.println("the linklist is empty");
				}
				break;
				
			case 'n':
				if (!mLinkList.isEmpty() && !mIterator.atEnd()) {
					mIterator.nextLink();
				}else {
					System.out.println("something happening");
				}
				break;
			
			case 'b':
				if (!mLinkList.isEmpty()) {
					System.out.print("input the word you want to insert ");
					System.out.flush();
					value = getInt();
					mIterator.insertBefore(value);
				}else {
					System.out.println("something happening");
				}
				break;
			
			case 'a':
				if (!mLinkList.isEmpty()) {
					System.out.print("input the word you want to insert ");
					System.out.flush();
					value = getInt();
					mIterator.inserAfter(value);
				}else {
					System.out.println("something happening");
				}
				break;
				
			case 'd':
				if (!mLinkList.isEmpty()) {
					value = mIterator.deleteLink();
					System.out.print("the deleted data is : " + value);
				}else {
					System.out.println("something happening");
				}
				break;
			default:
				System.out.println("Invalid entry");
				break;
			}
		}//end while
	}//end main
	
	public static String getString() throws IOException{
		InputStreamReader inReader = new InputStreamReader(System.in);
		BufferedReader buf = new BufferedReader(inReader);
		String mString = buf.readLine();
		return mString;
	}
	
	public static char getChar() throws IOException{
		char a;
		a = getString().charAt(0);
		return a;
	}
	
	public static int getInt() throws IOException{
		int a ;
		String s = getString();
		a = Integer.parseInt(s);
		return a;
	}
}

主函数的调用要注意对表是否为空的判断,以及对迭代器位置的判断,如果为空或者在尾部,应该做出相应的处理,这里更好应该在方法中就进行自动的判断,笔者在这里实现的是单链表,大家可以去尝试实现以下双向链表是如何实现的。

下面是运行结果:


好了,迭代器就讲到这里,大家有疑问可以评论。



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值