一、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;
}
}
}