一.简介
双向链表有2个指针,分别指向前一个结点、后一个节点。
基本结构如下:
二.实现
package com.vincent;
public class Main {
public static void main(String[] args) throws Exception{
LinkedList<Integer> list = new LinkedList<>();
for(int i=0;i<32;i++){
list.add(i);
}
System.out.println(list);
System.out.println("index -2:" + list.get(-2));
System.out.println("index 2:" + list.get(2));
list.remove(2);
System.out.println(list);
list.insert(0,100);
System.out.println(list);
}
}
class LinkedList<T> {
static class Node<T> {
T item;
Node<T> prev;
Node<T> next;
public Node(T item,Node<T> prev,Node<T> next) {
this.item = item;
this.prev = prev;
this.next = next;
}
@Override
public String toString() {
return item == null ? "null" : item.toString();
}
}
private Node<T> head;
private Node<T> rear;
private int size;
public void add(T item) {
if (head == null) {
head = new Node<>(item, null,null);
rear = head;
} else {
Node<T> node = new Node<>(item, rear,null);
rear.next = node;
rear = node;
}
size++;
}
private Node<T> nodeByIndex(int index){
int pos = (size + index) % size;
if(pos < 0 || pos > size){
throw new IndexOutOfBoundsException();
}
Node<T> node = head;
//判断目标节点位置,离头部近将从头部遍历,否则将从尾部遍历
if(pos <= size >> 1){
for(int i=0;i<pos;i++){
node = node.next;
}
}
else{
node = rear;
for(int i=0;i < size-1-pos;i++){
node = node.prev;
}
}
return node;
}
/**
* 获取指定位置节点元素,开始位置为0,索引支持负数,-1表示最后一个,-2表示倒数第2个
* @param index 节点索引
* @return
*/
public T get(int index){
Node<T> node = nodeByIndex(index);
return node.item;
}
public void insert(int index,T item){
Node<T> node = new Node<>(item,null,null);
if(index == 0){
node.next = head;
head.prev = node;
head = node;
}
else if(index == size){
rear.next = node;
node.prev = rear;
rear = node;
}
else{
Node<T> old = nodeByIndex(index);
node.prev = old.prev;
node.next = old;
old.prev.next = node;
old.prev = node;
}
size++;
}
public void remove(int index){
if(index == 0){
head = head.next;
if(size == 1){
rear = null;
}
}
else if(index == size-1){
Node<T> node = rear;
rear = node.prev;
rear.next = null;
node.prev = null;
}
else{
Node<T> node = nodeByIndex(index);
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = null;
node.prev = null;
}
size--;
}
public int size(){
return size;
}
@Override
public String toString() {
StringBuilder rst = new StringBuilder();
rst.append("[");
Node<T> pos = head;
while(pos != null){
rst.append(pos);
if(pos.next != null){
rst.append(",");
}
pos = pos.next;
}
rst.append("]");
return rst.toString();
}
}
效果图:
三.总结
相比单向链表,双向链表在插入节点时相对效率更好一些,可以实现反向遍历