2.4_线性表的链式存储结构_单链表具体实现
【思路简述】
看了很多网上的相关java实现单链表的思路,发现很多都没有设置一个头指针,因此,在我的自定义链表类MySingleLinkedList类中的head成员变量即为头指针,head结点其数据域默认为空,其指针域即为头指针,所以判断MySingleLinkedList对象是否为空,要判断其head.next()是否为空才可以。并在MySingleLinkedList的构造方法中同时初始化head,即 this.head=new Node();
【MySingleLinkedList.java实现类】
package com.Higgin.LinkList; /** * 单链表 * @author Higgin */ public class MySingleLinkedList { /** * 结点内部类 */ class Node{ private Object obj; //数据域 private Node next; //指针域 public Node(Object obj, Node next) { this.obj = obj; this.next = next; } public Node(Object obj){ this(obj,null); } public Node(){ this(null,null); } } /** * 头指针结点,其指针域为头指针(并不是头结点) */ private Node head; /** * 构造方法,其中实例化head头指针 */ public MySingleLinkedList(){ this.head=new Node(); //初始化head对象 } /** * 判断链表是否为空 */ public boolean isEmpty(){ //head结点(包含头指针),其数据域一直为null,利用其指针域来判断链表是否为空 return head.next==null; //只判断该指针域是否为空 } /** * 在链表最后添加元素 */ public void addLast(Object obj){ Node newNode=new Node(obj); Node curNode=head; //无需单独判断链表为空的情况 while(curNode.next!=null){ curNode=curNode.next; } curNode.next=newNode; } /** * 在第index位置之前插入对象obj */ public void add(int index,Object obj){ Node newNode=new Node(obj); //初始化被插入的结点 if(index==0){ newNode.next=head.next; //要插入的结点newNode的指针域指向head的指针域,可防止断链 head.next=newNode; //再将head的指针域指向新插入的结点 return; } //保证了 当前的index>0 Node curNode=this.getNode(index-1); //获取要插入位置(如2)的前一个结点(如1) newNode.next=curNode.next; curNode.next=newNode; } /** * 获取第index个结点(从头指针指向的那个结点开始算为第0个) */ public Node getNode(int index){ Node curNode=head; if(index<0||index>this.size()-1){ //要和数组的思维一样!注意head后面那个结点称为第0个,所以要size()-1 throw new IndexOutOfBoundsException("Index: "+index+" Size: "+this.size()); } int i=0; for(i=0;i<index && curNode!=null;i++){ curNode=curNode.next; //curNode不断向后走 } if(i!=index){ throw new IndexOutOfBoundsException("Index: "+index+" Size: "+this.size()); } return curNode.next; } /** * 获取第index个结点的数据域对象 */ public Object getObject(int index){ return getNode(index).obj; } /** * 获取链表的长度(不包含头指针) */ public int size(){ if(this.head.next==null){ return 0; }else{ Node curNode=head; int i=0; while(curNode.next!=null){ curNode=curNode.next; i++; } return i; } } /** * 删除第index个结点 */ public void deleteNode(int index){ if(index<0||index>size()-1){ //这里就排除了链表长度小于index的问题 throw new IndexOutOfBoundsException("Index: "+index+" Size: "+this.size()); } //删除链表的第一个元素 if(index==0){ Node curNode=head.next; head.next=curNode.next; //本质即 head.next=head.next.next.next; curNode.next=null; curNode.obj=null; } Node preNode=this.getNode(index-1); //获取要删除的那个结点的前一个结点 Node curNode=preNode.next; //要删除的那个结点 preNode.next=curNode.next; curNode.next=null; curNode.obj=null; } /** * 打印所有的结点 */ public void printAll(){ int i=0; while(i<this.size()){ //这里保证了 size()>0,至少有一个结点 System.out.println("第[ "+i +" ]个结点的数据域为: "+getObject(i).toString()); i++; } } }
【测试,与LinkedList进行对比】
public class TestMySingLinkedList { //测试addLast()和size()方法 @Test public void test1(){ MySingleLinkedList link=new MySingleLinkedList(); System.out.println(link.size()); link.addLast(1); link.addLast(1); link.addLast(1); link.addLast(1); System.out.println(link.size()); LinkedList l =new LinkedList(); System.out.println(l.size()); l.add(1); l.add(1); l.add(1); l.add(1); System.out.println(l.size()); } //测试获取链表第index个元素的对象的方法getObject(index) @Test public void test2(){ MySingleLinkedList link=new MySingleLinkedList(); // System.out.println(link.getObject(0)); //此时空链表,这里应该会报错 link.addLast(1); link.addLast(2); link.addLast(3); link.addLast(4); System.out.println(link.getObject(0)+"----"+link.getObject(1)+"----"+link.getObject(2)+"----"+link.getObject(3)); // System.out.println(link.getObject(5)); //超出范围,也会报错 LinkedList l =new LinkedList(); // System.out.println(l.get(0)); //此时空链表,这里应该会报错 l.add(1); l.add(2); l.add(3); l.add(4); System.out.println(l.get(0)+"----"+l.get(1)+"----"+l.get(2)+"----"+l.get(3)); } //测试在第index个结点之前插入结点 @Test public void test3(){ MySingleLinkedList link=new MySingleLinkedList(); // link.add(1,1); link.add(0,0); //0 link.add(1,1); //0,1 link.add(2,2); //0,1,2 // System.out.println(link.getObject(0)+"---"+link.getObject(1)+"---"+link.getObject(2)); // link.add(0,8); //8,0,1,2 // System.out.println(link.getObject(0)+"---"+link.getObject(1)+"---"+link.getObject(2)+"---"+link.getObject(3)); // link.add(1,6); //8,1,0,1,2 // System.out.println(link.getObject(0)+"---"+link.getObject(1)+"---"+link.getObject(2)+"---"+link.getObject(3)+"---"+link.getObject(4)); // LinkedList l =new LinkedList(); // l.add(1,2); l.add(0,0); //0 l.add(1,1); //0,1 l.add(2,2); //0,1,2 l.add(4,88); // System.out.println(l.get(0)+"---"+l.get(1)+"---"+l.get(2)); // l.add(0,8); //8,0,1,2 // System.out.println(l.get(0)+"---"+l.get(1)+"---"+l.get(2)+"---"+l.get(3)); // l.add(1,6); //8,1,0,1,2 // System.out.println(l.get(0)+"---"+l.get(1)+"---"+l.get(2)+"---"+l.get(3)+"---"+l.get(4)); } //测试删除第index个结点 @Test public void test4(){ MySingleLinkedList link=new MySingleLinkedList(); link.addLast(0); link.add(0, 1); link.addLast(9); link.printAll(); link.deleteNode(1); link.printAll(); } }