java链表的结构_用Java实现链表结构

这里主要记录了一下学习用Java实现链表的方法。假设你有一点Java基础,了解接口、内部类的内容,同时也学过数据结构中链表的内容,对设计模式中的工厂方法和迭代方法知道一些,(因为这里将不介绍这些基础知识,我的水平也讲不清)又想了解在Java中实现链表,那么接着看吧。(最近读严老师的帖子说应该在博文中说明帖子的读者范围,不要浪费大家的时间,这里响应一下)。

首先声明一下,本人菜鸟一只,近日闲来无事做做coding打发光阴,限于我对技术的认知水平,文中说的不对的地方一定不少,如果有热心人能帮忙指出,不胜感激!!批评者,请口下留情,不要打击了俺幼小地心灵。。。。。

正文:

最近写程序的过程中想用链表的方法把一些数据组织起来,C/C++的链表倒是比较熟,但是Java里还没写过。在网上搜了搜,Java中的链表应该是有以下几种方法:

按链表的组织形式分有ArrayList和LinkList两种。ArrayList内部其实是用数组的形式实现链表,比较适合链表大小确定或较少对链表进行增删操作的情况,同时对每个链表节点的访问时间都是constant;而LinkList内部以一个List实现链表,比较适合需要频繁对链表进行操作的情况,对链表节点的访问时间与链表长度有关O(N)。

另外,根据实现形式可以分为直接式(想不出什么合适的名字,姑且这样吧)和使用Iterator(迭代模式)两种方法。直接式的实现方法和C/C++中的写法差不多;而使用Iterator时,需要实现java.lan中的Iterable接口(或者也可以自己在链表内部定义自己的Iterator method)

关于直接实现链表好,还是使用迭代模式好这个问题,有两个帖子可以看看:

1.  http://topic.csdn.net/t/20050722/17/4162226.html这篇帖子,虽然短小,但也说出了一些使用迭代模式设计链表的好处;

2.后来又看到了http://www.java63.com/design_pattern/iterator_pattern.html这篇帖子,觉得说的比较清楚了。

我这里再捡主要的说一下:

使用迭代模式的优点:

1,实现功能分离,简化容器接口。让容器只实现本身的基本功能,把迭代功能委让给外部类实现,符合类的设计原则。

2,隐藏容器的实现细节。

3,为容器或其子容器提供了一个统一接口,一方面方便调用;另一方面使得调用者不必关注迭代器的实现细节。

4,可以为容器或其子容器实现不同的迭代方法或多个迭代方法。

我觉得第4点说的很好,对于一堆数据而言,不同的人(或业务逻辑)使用它的方式也不尽相同,定义一个theIterator继承Iterator,不仅提供next,hasNext以及remove这个最小的操作集合,同时也可以提供更多的其它方法。在theIterator的实现类中,具体实现不同的迭代方法,比如顺序、逆序或根据其它语义进行遍历等,再通过类厂的方式将一个theIterator实现的对象交给用户使用。

下面我给出两个例子:

首先是直接式实现链表的例子,这个例子只提供了几种链表操作的基本方法,仅用于示意:

public class MyList {

private class Node{

public Node pre;

public Node next;

public AnyType data;

public Node(AnyType d, Nodep, Node n){}

public Node(){}

}

private int theSize;

private Node Header;

private Node Tail;

public MyList(){}

public void add(AnyType item){}

public boolean isEmpty(){}

public int size(){}

public AnyType get( int idx){}

public void print(){}

}

Node类定义了双向链表中节点的结构,它是一个私有类,而其属性和构造函数都是公有的,这样,其父类可以直接访问其属性,而外部类根本不知道Node类的存在。Data是节点中的数据与,pre指向前一个Node节点,next指向后一个Node节点。其构造函数的实现如下,不解释:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

public Node(AnyType d, Nodep, Node n){

this.data = d;

this.pre = p;

this.next = n;

}

public Node(){

this.data = null;

this.pre = null;

this.next = null;

}

下面我们看一下链表的构造函数实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

public MyList(){

theSize = 0;

Header = new Node(null,null,null);

Tail = new Node(null,Header,null);

Header.next = Tail;

}

我们构造了一个带有头、尾节点的双向链表,头节点的Next指向尾节点,为节点的pre指向头节点。链表长度起始为0。

继续贴上链表类其它方法的实现,不解释了,应该比较清楚:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

public void add(AnyType item){

Node aNode = new Node(item,null,null);

Tail.pre.next = aNode;

aNode.pre = Tail.pre;

aNode.next = Tail;

Tail.pre = aNode;

theSize++;

}

public boolean isEmpty(){

return ( theSize == 0);

}

public int size(){

return theSize;

}

public AnyType get( int idx){

if(idx > theSize-1 || idx < 0)

throw new IndexOutOfBoundsException();

Node current = new Node(null,Header,null);

for(int i = 0; i

current = current.next;

return current.data;

}

public void print(){

Node current = Header.next;

while(current.next != null){

//如果AnyType是你自己定义//的数据类型,那么请务必提供//一个toString方法,要么就不//要在链表里实现print方法。 System.out.println(current.data.toString());

current = current.next;

}

}

第二个例子是用迭代方法实现链表的例子,下面是类定义:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

public class MyListItr implements Iterable {

private class Node{

public Type data;

public Node pre;

public Node next;

public Node(){}

public Node(Type d, Node p, Node n){}

}

private Node Header;

private Node Tail;

private int theSize;

public MyListItr(){}

public void add(Type item){}

public void print(){}

public int size(){}

@Override

public Iterator iterator() {}

private class MyListIterator implements Iterator{

@Override

public boolean hasNext() {}

@Override

public Type next() {}

@Override

public void remove() {}

}

}

这里主要说一下与前面例子不同的地方:MyListItr类实现了java.lan.Itrable接口,因此我们必须实现其public Iterator iterator() {}方法,它的返回值是一个迭代器对象,那么我就定义一个内部私有类——MyListIterator,这个类实现了iterator接口。在public Iterator iterator()方法中,我就构造这么一个MyListIterator的对象并返回。

Iterator接口有三个方法是我们必须实现的,hasNext,next和remove,这是迭代操作的最小集合了。对于不同的迭代器执行方式,我们可以定义多个类似MyListIterator这样的实现类,只要在链表类中的iterator()方法中把具体实现类的对象返回给用户就OK了。

罗嗦两句:我感觉如果我们定义链表类时,如果不继承Iterable接口,而是直接在类内部提供public theIterator Iterator()方法,theIterator是一个自定义接口,继承自Iterator接口,这样我们可以提供遵循theIterator接口的各种迭代方式的不同实现类,并通过一个类厂方法在链表的public theIterator Iterator()方法中把具体迭代实现类的对象交给用户,以此就可以根据不同的需求,提供链表的多种迭代方式。我觉得这种方法是可行的,但并没有具体实验。

下面只贴出链表iterator()方法和迭代实现类的MyListIterator代码,其它方法就不重复贴了:

@Override

public Iterator iterator() {

return new MyListIterator();

}

private class MyListIterator implements Iterator{

Node current = Header.next;

@Override

public boolean hasNext() {

return (current != Tail);

}

@Override

public Type next() {

if(!hasNext())

throw new IndexOutOfBoundsException();

Type item = current.data;

current = current.next;

return item;

}

@Override

public void remove() {

if( !hasNext())

throw new NoSuchElementException();

current.pre.next = current.next;

current.next.pre = current.pre;

current = current.next;

theSize--;

}

}

测试代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

public class MyListTest {

/***@paramargs*/

public static void main(String[] args) {

MyList intList = new MyList();

for (int i = 0; i < 10; i++) {

intList.add(i);

}

intList.print();

MyListItr itrList = new MyListItr();

for (int i = 0; i < 10; i++) {

ItemInfo aItem = new ItemInfo("name_" + i, "score_" + i);

itrList.add(aItem);

}

itrList.print();

System.out.println("=======print using iterator type_1==========");

Iterator Itor = itrList.iterator();

for (ItemInfo str : itrList)

System.out.println(str);

System.out.println("=======print using iterator type_2==========");

while(Itor.hasNext())

System.out.println(Itor.next().toString());

System.out.println("-------------------after remove----------------");

while (Itor.hasNext())

Itor.remove();

while(Itor.hasNext())

System.out.println(Itor.next().toString());

}

}

其中 ItemInfo的定义如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngView Code

public class ItemInfo {

String name;

String score;

public ItemInfo(String n, String s){

name = n; score = s;

}

public ItemInfo(){

name = null; score = null;

}

public String toString(){

String str = name +" "+ score;

return str;

}

}

至此,Java实现链表的方法基本上也就清楚了,希望我说清楚了,不要让各位如同嚼蜡:) 这里是一个简单的例子:MYLList

下一步我想做以下工作:

试一下通过类厂的方法提供多种链表的迭代方式;

如何让多线程访问链表时保证操作不乱掉。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值