学过集合的读者都知道,ArrayList的底层实现是用数组实现,而LinkedList的实现则是用链表实现。那么什么是链表呢?其实可以把它比喻成一串珠子,珠子通过线来串连起来。要想找到中间的珠子,就只能通过第一个珠子或者最后一个珠子,一个一个的找下去,直到找到所要的珠子。
链表分为单向链表和双向链表,单向链表是指,只能通过前一个珠子找到后一个珠子或者只能通过后一个珠子找到前一个珠子,关联关系是单向的;双向链表是指,既能通过前一个珠子找到后一个珠子,同时也能通过后一个珠子找到前一个珠子,关联关系是双向的。
现在笔者就以双向链表来实现LinkedList。要想通过链表来存放元素,同时还能通过每一个元素来找到下一个或者前一个对象,那么该怎样设计数据结构呢?首先我们将一个珠子当做成一个节点(Node),该节点要实现存放元素(obj),同时还能找到前一个节点(prev)和下一个节点(next),那么我们可以将一个珠子分成三个小块。如图:
根据上面的设计,那么整个双向链表结构就可以描述成如下的图:
这样基本的数据结构我们就定义完成了,接下来就用实际的代码来实现:
public class MylinkedList {
private Node first;//第一个节点
private Node last;//最后一个节点
private int size;
//内部类
private class Node {
Node prev;//前一个节点
Object obj;//当前节点的元素
Node next;//后一个节点
Node(Node prev, Object obj, Node next) {
this.prev = prev;
this.obj = obj;
this.next = next;
}
}
public MylinkedList() {
}
//长度
public int size(){
return size;
}
//空判断
public boolean isEmpty(){
return size==0;
}
//越界判断
public void rangeCheck(int index){
if(index<0||index>=size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//返回索引处的元素
public Node node(int index){
rangeCheck( index);
Node temp=first;
if(temp!=null){
for(int i=0;i<index;i++){
temp=temp.next;//保证最后一个元素可以取到值
}
}
return temp;
}
//添加最后一个元素
public void linkLast(Object obj){
Node temp = new Node(last, obj, null);
if(first==null){
first=last=temp;
}else {
last.next=temp;//最后一个元素
last=temp; //最后一个元素的节点执向
}
}
//将元素添加到指定节点
public void linkBefore(Object obj,Node node){
Node temp = new Node(null, obj, node);
Node up = node.prev;
if(up!=null){//存在上一个节点
up.next=temp;
temp.prev=up;
node.prev=temp;
}else {//node是第一节点
first=temp;
}
}
//添加元素
public void add(Object obj){
linkLast(obj);
size++;
}
//被占领的节点全往后移动
public void add(int index,Object obj){
//当index=size时,元素添加到最后一个
if(index<0||index>size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
if(index==size){
linkLast(obj);
}else {
linkBefore(obj, node(index));
}
size++;
}
//获取指定位置的元素
public Object get(int index){
rangeCheck(index);
Node temp = node(index);
return temp.obj;
}
//设置指定位置的元素
public void set(int index,Object obj){
rangeCheck(index);
Node temp = node(index);
temp.obj=obj;
}
//返回某一个元素的索引,找到就返回,找不到返回-1
public int indexOf(Object obj){
int index=0;
for(Node temp =first;temp!=null;){
if(temp.obj.equals(obj)){
return index;
}
temp= temp.next;
index++;
}
return -1;
}
//删除指定元素
public void remove(int index){
rangeCheck(index);
Node temp = node(index);
//获得删除节点的上一个节点和下一个节点
Node up = temp.prev;
Node down = temp.next;
//如果删除的是第一个节点
if(up==null){
// down.prev=null;
temp=null;
first=down;
size--;
return ;
}
if(down==null){
//up.next=null;
temp=null;
last=up;
size--;
return ;
}
up.next=down;
down.prev=up;
size--;
}
//删除指定元素
public void remove(Object obj){
int index=0;
for(Node temp =first;temp!=null;){
if(temp.obj.equals(obj)){
temp= temp.next;
remove(index);
}
temp= temp.next;
index++;
}
}
//清空元素
public void clear(){
for(Node temp =first;temp!=null;){
Node next = temp.next;
temp.prev=null;
temp.obj=null;
temp.next=null;
temp=next;
}
size=0;
first=last=null;
}
//打印出结果
public void Result(){
int i =0;
for(Node temp =first;temp!=null;){
Object obj = temp.obj;
System.out.println("结果"+i+"= "+obj);
temp=temp.next;
i++;
}
}
public static void main(String[] args) {
MylinkedList myLisk = new MylinkedList();
System.out.println("添加元素========");
myLisk.add("lan");
myLisk.add("po");
myLisk.add("zui");
myLisk.add("sha");
myLisk.Result();
System.out.println("指定为添加元素========");
myLisk.add(1, "lu");
myLisk.Result();
System.out.println("获取指定元素========");
Object object = myLisk.get(1);
System.out.println(object);
System.out.println("设置指定元素========");
myLisk.set(1, "ha");
myLisk.Result();
System.out.println("获取指定元素的索引========");
int indexOf = myLisk.indexOf("zui");
System.out.println(indexOf);
System.out.println("根据索引删除指定元素========");
myLisk.remove(1);
myLisk.Result();
System.out.println("删除某一个元素========");
myLisk.remove("zui");
myLisk.Result();
System.out.println("清空========");
myLisk.clear();
}
}
结果如下