链表的百度百科的解释如下:
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。
下面是自己的实现:
package com.centnet.anfs.internal.caseInfo.properties;
import java.util.Objects;
/**
* @author by wml on 2019/8/12.
*/
public class MyLinkedList<E> {
private class Node{
E e;
Node next;
public Node(E e,Node next){
this.e = e;
this.next = next;
}
public Node(){
this(null,null);
}
public Node(E e){
this(e,null);
}
@Override
public String toString(){
System.out.println("E:"+e+"NextNode:"+next);
return "E:"+e+"NextNode:"+next;
}
}
private int size;
private Node dummyHead;
public MyLinkedList(){
dummyHead = new Node(null,null);
size = 0;
}
public void add(int index,E e){
if(index<0 || index>size){
throw new IllegalArgumentException("索引越界问题");
}
Node beforeNode = dummyHead;
for(int i=0;i<index;i++){
beforeNode = beforeNode.next;
}
beforeNode.next = new Node(e,beforeNode.next);
size++;
}
public void addFirst(E e){
add(0,e);
}
public void addLast(E e){
add(size,e);
}
public E get(int index){
if(index<0 || index>=size){
throw new IllegalArgumentException("索引越界问题");
}
Node returnNode = dummyHead.next;
for(int i=0;i<index;i++){
returnNode = returnNode.next;
}
return returnNode.e;
}
public E getFirst(){
return get(0);
}
public E getLast(){
return get(size-1);
}
public void set(int index,E e){
if(index<0 || index>=size){
throw new IllegalArgumentException("索引越界问题");
}
Node node = dummyHead.next;
for(int i=0;i<index;i++){
node = node.next;
}
node.e = e;
}
public boolean isContains(E e){
Node node = dummyHead.next;
for(int i=0;i<size;i++){
if(node.e.equals(e)){
return true;
}
node = node.next;
}
return false;
}
public void delete(int index){
if(index<0 || index>=size){
throw new IllegalArgumentException("索引越界问题");
}
Node beforeNode = dummyHead;
for(int i=0;i<index;i++){
beforeNode = beforeNode.next;
}
Node deleteNode = beforeNode.next;
beforeNode.next =deleteNode.next;
deleteNode.next = null;
size--;
}
public void deleteFirst(){
delete(0);
}
public void deleteLast(){
delete(size-1);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("size:").append(size).append(";");
Node node = dummyHead.next;
while (node!=null){
builder.append(node.e).append(">");
node = node.next;
}
return builder.toString();
}
public static void main(String[] args) {
MyLinkedList<Integer> integerMyLinkedList = new MyLinkedList<>();
for(int i=0;i<10;i++){
integerMyLinkedList.addLast(i);
}
System.out.println(integerMyLinkedList.toString());
System.out.println(integerMyLinkedList.isContains(10));
System.out.println(integerMyLinkedList.get(5));
System.out.println(integerMyLinkedList.getFirst());
System.out.println(integerMyLinkedList.getLast());
integerMyLinkedList.set(5,55);
System.out.println(integerMyLinkedList.toString());
integerMyLinkedList.delete(5);
System.out.println(integerMyLinkedList.toString());
integerMyLinkedList.deleteFirst();
System.out.println(integerMyLinkedList.toString());
integerMyLinkedList.deleteLast();
System.out.println(integerMyLinkedList.toString());
}
}
讨论一下链表的各个操作的时间复杂度分析:
添加操作:set(索引,元素):均摊来说的话:这个得复杂度是O(n)的,所以不建议使用链表进行添加操作,他需要去遍历索引之前的元素去找到插入节点的前一个元素;而addFirst的操作是O(1),因为不需要去遍历
删除操作同理;
获取元素同理,因为在链表中没有数组中的索引的这种实现,所以寻找元素也是相对耗时间的;