> 文章列表 > Java数据结构和算法之第五章、LinkedList与链表

Java数据结构和算法之第五章、LinkedList与链表

Java数据结构和算法之第五章、LinkedList与链表

一、ArrayList的缺陷

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {// ...
// 默认容量是10private static final int DEFAULT_CAPACITY = 10;//...
// 数组:用来存储元素transient Object[] elementData; // non-private to simplify nested class access// 有效元素个数private int size;public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: " +initialCapacity);}} // ...}

由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构。


二、链表

2.1链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。(逻辑上连续物理上不连续)

实际中链表的结构非常多样,通过节点组成。以下情况组合起来就有8种链表结构:
1.单向 带头 循环链表   2.单向 带头 非循环链表   3.单向 不带头 循环链表 4.单向 不带头 非循环链表 

5.双向 带头 循环链表   6.双向 带头 非循环链表   7.双向 不带头 循环链表   8.双向 不带头 非循环链表

2.1.1单向和双向

2.1.2带头或者不带头


 2.1.3循环或者非循环

 2.1.4重点

1.无头单向非循环链表

结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2. 无头双向链表

在Java的集合框架库中LinkedList底层实现就是无头双向循环链表

2.2链表的实现

// 1、无头单向非循环链表实现
public class IndexOutOfBounds extends RuntimeException{public IndexOutOfBounds(String message){System.out.println(message);}
}public class MySingleList {//节点的创建class ListNode{//值域public int val;//引用变量public ListNode next;public ListNode(int val){this.val=val;}}//永远指向头节点public ListNode head;public void createList(){ListNode node1=new ListNode(12);ListNode node2=new ListNode(23);ListNode node3=new ListNode(34);ListNode node4=new ListNode(45);ListNode node5=new ListNode(56);node1.next=node2;node2.next=node3;node3.next=node4;node4.next=node5;head.next=node1;}public void show(){ListNode cur=head;while(cur!=null){System.out.println(cur.val);cur=cur.next;}System.out.println();}//头插法public void addFirst(int data){ListNode cur=new ListNode(data);cur.next=head;head=cur;}//尾插法public void addLast(int data){ListNode node=new ListNode(data);if(head==null){head=node;return ;}ListNode cur=head;while(cur!=null){cur=cur.next;}//cur 指向的节点是尾巴节点cur.next=node;}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data){int len=size();if(index<0||index>len){throw new IndexOutOfBounds("任意位置插入数据的时候,index的位置不合法:"+index);}if(index==0){addFirst(data);return ;}if(index==len){addLast(data);return ;}ListNode node=new ListNode(data);ListNode cur=findIndex(index);node.next=cur.next;cur.next=node;}private ListNode findIndex(int index){ListNode cur=head;while(index-1!=0){cur=cur.next;index--;}return cur;}//查找是否包含关键字key是否在单链表当中public boolean contains(int key){ListNode cur=head;while(cur!=null){//如果value值为空,需要使用equals方法比较if(cur.val==key){return true;}cur=cur.next;}return false;}//删除第一次出现关键字为key的节点public void remove(int key){if(head==null){return ;}if(head.val==key){head=head.next;return ;}ListNode prev=searchPrev(key);if(prev==null){System.out.println("没有这个数据!");return ;}ListNode del=prev.next;prev.next=del.next;}private ListNode searchPrev(int key){ListNode prev=head;while(prev.next!=null){if(prev.next.val==key){return prev;}else{prev=prev.next;}}return null;}//删除所有值为key的节点public void removeAllKey(int key){if(head==null){return ;}//第一种删除头节点方法/ while(head.val==key){*   head=head.next;* }* */ListNode cur=head.next;ListNode prev=head;while(cur!=null){if(cur.val==key){prev.next=cur.next;cur=cur.next;}else{prev=cur;cur=cur.next;}}//第二种删除头节点方法if(head.val==key){head=head.next;}}//得到单链表的长度public int size(){int count=0;ListNode cur=head;while(cur!=null){count++;cur=cur.next;}return count;}public void clear() {//this.head=null;while(head!=null){ListNode HeadNext=head.next;head.next=null;head=HeadNext;}}
}