1. ArrayList的缺陷
ArrayList底层使用数组来存储元素
由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后 搬移,时间复杂度为O(n),效率比较低。因此ArrayList不适合做任意位置插入和删除比较多的场景。
因此:java 集合中又引入了LinkedList,即链表结构。
2. 链表
链表的概念及结构
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
注意:
1.从上图可看出,链式结构在逻辑上是连续的,但是在物理上不一定连续
2.现实中的结点一般都是从堆上申请出来的
3.从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续
1. 单向或者双向
2. 带头或者不带头
3. 循环或者非循环
3 模拟LinkedList的实现
我们先来定义一些数据:
public class MySingleLinkedList {
class ListNode{
public int val;
public ListNode nest;
public ListNode(int val) {
this.val = val;
}
}
public ListNode head;//代表链表头节点
}
如果想要全部遍历完 那么 head != null而不是head.next != null
那样会少遍历最后一个值。
1头插法:
public void addFirst(int val){
ListNode node = new ListNode(val);
node.next = head;
head = node;
2.尾插法:
public void addLast(int val) {
ListNode node = new ListNode(val);
if(head == null) {
head = node;
return;
}
ListNode cur = head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
3任意位置插入:
public void addIndex(int index,int val) {
//1.判断index的合法性
try {
checkIndex(index);
}catch (IndexNotLegalException e) {
e.printStackTrace();
}
//2.index == 0 || index == size()
if(index == 0) {
addFirst(val);
return;
}
if(index == size()) {
addLast(val);
return;
}
//3. 找到index的前一个位置
ListNode cur = findIndexSubOne(index);
//4. 进行连接
ListNode node = new ListNode(val);
node.next = cur.next;
cur.next = node;
}
private ListNode findIndexSubOne(int index) {
int count = 0;
ListNode cur = head;
while (count != index-1) {
cur = cur.next;
count++;
}
return cur;
}
4查找是否包含关键字val是否在单链表当中
public boolean contains(int val) {
ListNode cur = head;
while (cur != null) {
if(cur.val == val) {
return true;
}
cur = cur.next;
}
return false;
}
5删除出现一次关键字为val的节点
public void remove(int val){
if(head == null){
return;
}
if (head.val==val){
head = head.next;
return;
}
ListNode cur = head;
while (cur.next != null){
if (cur.next.val==val){
ListNode del =cur.next;
cur.next=del.next;
}
cur=cur.next;
}
}
6删除所有值为key的节点
如果要删的是head.val,可以使代码走完在走一遍就行 或者把if改成while语句。
public void removeAllKey(int val) {
//1. 判空
if(this.head == null) {
return;
}
//2. 定义prev 和 cur
ListNode prev = head;
ListNode cur = head.next;
//3.开始判断并且删除
while(cur != null) {
if(cur.val == val) {
prev.next = cur.next;
//cur = cur.next;
}else {
prev = cur;//prev = prev.next;
//cur = cur.next;
}
cur = cur.next;
}
//4.处理头节点
if(head.val == val) {
head = head.next;
}
}
7 清空链表
public void clear() {
//head = null;
ListNode cur = head;
while (cur != null) {
ListNode curN = cur.next;
//cur.val = null;
cur.next = null;
cur = curN;
}
head = null;
}