Java与C和C++相比一个最大的不同在于,Java去掉了C中最有特色的特征:指针。其结果使初学者和程序员避免了很多犯又于指针引起的莫名其妙的错误的可能,也使程序员不能够利用指针这种过于灵活的手段用于进行比如溢出这样的不利于系统安全的操作。但是,由于没有了指针,似乎在教科书中的利用指针可以方便实现的如链表这样的数据结构在Java中就更为麻烦一些了。Java的java.util库中因此提供了集合Collection,列表LinkedList一类的类提供这方面的使用。其实,由于Java中依然存在引用操作,所以,利用引用还是可以比较方便地实现链表这一类数据结构的。比如我们可以写如下的一段程序来基本实现单链表的操作。这里,我们考虑链表的每个节点是对象,而不是具体的简单数据类型。
public class test {//测试类
public static void main(String[] arg) {//测试链表类
int k[]={1,2,3,4,5};//定义一个数组对象
olist ol=new olist();//生成一个链表实例
ol.add(new String("test"));//添加一个字符串对象到链表
ol.add(new Integer(2));//添加整型对象到链表
ol.add(k);//添加数组对象到链表
ol.add(new String("string2"));//添加字符串对象到链表
System.out.print("The List:"); print(ol);//打印链表
int n=4;
ol.remove(n);//删除一个结点
System.out.print("Delete "+n+"th member:"); print(ol);//打印删除后的链表
ol.add(new String("newOne"));//添加一个字符串到链表
System.out.print("Add agin:"); print(ol);//打印链表
}
public static void print(olist l) {//打印链表函数
for(int i=0; i<l.getLength(); i++)
System.out.print(" "+l.getData(i));
System.out.println();
}
}
class olist {//链表类
class node {//内部类,用于存储节点。在C语言中,往往是定义类似的结构来存储节点
private Object obj;//数据对象
private node next;//下指针
private node(Object o) {//节点构造函数。与C相比,可以在这里封装添加节点的赋值操作。而C中需要在相应的添加函数里对于新的节点结构实例赋值
obj=o;
next=this;//保证尾节点的下指针指向自身
}
}
private node head,tail;//定义链表头、尾指针
private int length;//链表长度
public olist() {//空链表,构造函数
head=null;
tail=null;
length=0;
}
public void add(Object obj) {//添加节点到链表尾
node n=new node(obj);//这里,利用类特性生成节点,并利用构造函数完成节点赋值
if(length>0) tail.next=n;//修改尾节点下指针
tail=n;//修改尾指针
if (length==0) head=n;//修改链表头指针
length++;
}
public void remove(int i) {//删除第i个节点
if(i<1 || i>length) return;//i非法,返回
node work=head;
for(int k=1; k<i-1; k++) work=work.next;//查找节点
if(tail==work.next && i!=1) tail=work;
if(i==1) head=head.next;
else work.next=work.next.next;
length--;
}
public int getLength() {return length; }//返回链表长度
public Object getData(int i) {//返回链表i节点数据对象
if(i<0 || i>=length) return null;
node work=head;
for(int k=0; k<i; k++) work=work.next;
return work.obj;
}
}
上例的运行结果如下:
The List: test 2 [I@ 1a 5ab41 string2
Delete 4th member: test 2 [I@ 1a 5ab41
Add agin: test 2 [I@ 1a 5ab41 newOne
其实和C与C++的链表实现相比,Java的方案和其类似。只不过由于Java去掉了释放内存的语言特性,而改由Java自身管理,在程序中,再也不用delete任何对象。这似乎给我一种不安全的感觉,不知道是否会因此引起内存泄漏。但想想,主要是自己不理解Java的垃圾收集机制,如果理解了,就能够清楚地知道上述操作中是否会引起内存泄漏了,这里,我也只有相信Java能够比我自己能更好地处理内存释放的操作了。
上述链表只能用于对象的操作,对于非对象的简单数据类型的链表,则可以简单地将 node 类中的节点数据定义为相应的类型,并进行相应的操作即可。从某种意义上讲,理解了 Java 的引用,就可以简单地实现很多 C 中类似的东西。其实引用本身就在某种程度上作为指针使用,只不过是一个有限制的,更安全的指针。在 C++ 中之所以要添加引用的要素,其实也可以说有相似的道理。