前言
链表的特点:插入删除效率高,查找效率低;
链表结构
从链表结构可以看出:
- 每个元素都指向下一个元素,当指向NULL时表示已到末尾;
- 对于元素查找,需要从头遍历查找下一个元素,直到找到;
- 对于元素新增删除,需要找到前一个元素,修改指针指向;
链表插入元素
思路:找到位置的前一个元素1
,将888
待插入元素指向1
的下一个元素2
,同时修改1
的下一个元素为888
即可;
链表删除元素
思路:找到待删除元素888
位置的前一个元素1
,将1
的下一个元素指向888
的下一个元素2
,同时将888
的下一个元素指向NULL
,即可实现将888
从链表中删除;
代码实现
这里引入虚拟头结点
概念,用于方便操作,其结构如下:
package com.sjgd.linked;
import androidx.annotation.NonNull;
/**
* 自定义实现链表
*
* @author xixu
*/
public class LinkedList<E> {
/**
* 虚拟头结点【实际上不存在,为链表第一个元素的前结点】
*/
private Node dummyHead;
/**
* 当前元素容量
*/
private int size;
public LinkedList() {
dummyHead = new Node(null, null);
size = 0;
}
/**
* 获取链表元素个数
*
* @return
*/
public int getSize() {
return size;
}
/**
* 判断当前元素是否为空
*
* @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 往链表任意位置index处插入元素e
*
* @param index 任意位置
* @param e 相关元素
*/
public void add(int index, E e) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("Add Failed, Illegal Index.");
}
Node prev = dummyHead;
for (int i = 0; i < index; i++) {
// 找到要插入位置的前一个Node
prev = prev.next;
}
// Node node = new Node(e);
// node.next = prev.next;
// prev.next = node;
prev.next = new Node(e, prev.next);
size++;
}
/**
* 往链表首部插入元素e
*
* @param e 元素e
*/
public void addFirst(E e) {
add(0, e);
}
/**
* 往链表尾部插入元素e
*
* @param e 元素e
*/
public void addLast(E e) {
add(size, e);
}
/**
* 获取index下标处的元素E
*
* @param index 元素下标
* @return
*/
public E get(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("Get Failed, Illegal Index.");
}
Node current = dummyHead.next;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.e;
}
/**
* 获取链表第一个元素
*
* @return
*/
public E getFirst() {
return get(0);
}
/**
* 获取链表最后一个元素
*
* @return
*/
public E getLast() {
return get(size - 1);
}
/**
* 修改index下标处的元素为e
*
* @param index 对应下标
* @param e 元素e
*/
public void set(int index, E e) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("Set Failed, Illegal Index.");
}
Node current = dummyHead.next;
for (int i = 0; i < index; i++) {
current = current.next;
}
current.e = e;
}
/**
* 查找链表中是否包含e
*
* @param e 查找的e
* @return
*/
public boolean contains(E e) {
Node current = dummyHead.next;
while (current != null) {
//说明链表没有遍历结束
if (current.e.equals(e)) {
return true;
}
current = current.next;
}
return false;
}
/**
* 移除index下标处的元素
*
* @param index
* @return
*/
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("remove Failed, Illegal Index.");
}
//找到要删除index的前一个元素
Node prev = dummyHead;
for (int i = 0; i < index; i++) {
prev = prev.next;
}
//要删除的Node结点
Node result = prev.next;
prev.next = result.next;
result.next = null;
size--;
return result.e;
}
/**
* 移除第一个元素
*
* @return
*/
public E removeFirst() {
return remove(0);
}
/**
* 移除最后元素
*
* @return
*/
public E removeLast() {
return remove(size - 1);
}
@NonNull
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node current = dummyHead.next;
while (current != null) {
sb.append(current.e);
sb.append("->");
current = current.next;
}
sb.append("NULL");
return sb.toString();
}
private class Node {
private E e;
private Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this(e, null);
}
public Node() {
this(null, null);
}
@NonNull
@Override
public String toString() {
return e.toString();
}
}
}
上述代码实现时间复杂度
- 增删改查O(n)
- 如果是首部操作,均为O(1)