一、ArrayList的缺陷
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // ... // 默认容量是10 private 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; } } }