您的位置:首页 > 编程语言 > Java开发

java手动实现双向链表LinkedList

2018-01-12 15:22 507 查看
一、LinkedList原理介绍

LinkedList是java中重要的List集合,其内部是一个双向链的数据结构。插入和删除的效率比ArrayList高,之前手动实现的ArrayList,因为插入和删除没有数组的复制工作,如果想在下标为index位置插入元素则通过从头部或者尾部开始查找,找到index原始位置的元素,则修改原始位置index元素的Node中的上一个元素,以及元素index元素前一个元素Node的下一个元素。只需要修改两个元素就可以实现元素的插入。(List元素越大则LinkedList插入/删除的效率相比ArrayList)会更好。

二、LinkedList实现代码

package list;

import java.util.NoSuchElementException;

/**
* 实现一个双向链表
* @author ocean
*
*/
public class MyLinkedList<E> {
private int size;

private Node<E> firstNode;

private Node<E> lastNode;

private class Node<E>{
private E item;
private Node<E> preNode;
private Node<E> nextNode;
public Node(E item, Node<E> preNode, Node<E> nextNode) {
this.item = item;
this.preNode = preNode;
this.nextNode = nextNode;
}
}

/**
* 根据下标获取元素
* @param index
* @return
*/
public E get(int index) {
//数组越界
if(!checkElementIndex(index)) {
throw new IndexOutOfBoundsException();
}
return getNode(index).item;
}

/**
* 尾部追加一个元素
* @param e
* @return
*/
public boolean add(E e) {
linkedLast(e);
return true;
}
/**
* 头部插入一个元素
* @param e
* @return
*/
public boolean addFirst(E e) {
linedFirst(e);
return true;
}

/**
* 向下标index插入元素
* @param index
* @param e
* @return
*/
public boolean add(int index,E e) {
if(index==size) {
linkedLast(e);
}else {
addBefore(index, e);
}
return true;
}

/**
* 根据下标删除元素
* @param index
* @return
*/
public E remove(int index) {
return unlink(getNode(index));
}

/**
* 删除第一个元素
* @return
*/
public E removeFirst() {
return unlinkFirst();
}

public E removeLast() {
return unlinkLast();
}

E unlinkLast() {
Node<E> l = lastNode;
if(l == null) {
throw new NoSuchElementException();
}
E element = l.item;
Node<E> pre = l.preNode;
l.item = null;//help gc
l.preNode = null;//help gc
if(pre == null) {
firstNode = null;
}else {
lastNode = pre;
}
size --;
return element;
}

E unlinkFirst() {
Node<E> f = firstNode;
if(f == null) {
throw new NoSuchElementException();
}
E element = f.item;
Node<E> next = f.nextNode;
f.item = null;
f.nextNode = null;
if(next == null) {
lastNode = null;
}
firstNode = next;
size --;
return element;
}

/**
* 向链表尾部插入元素
* @param e
*/
void linkedLast(E e) {
Node<E> x = lastNode;
Node<E> newNode = new Node<>(e, x, null);
lastNode = newNode;
if(x ==null) {
firstNode = newNode;
}else {
x.nextNode = newNode;
}
size ++;
}

/**
* 向链表头部插入元素
* @param e
*/
void linedFirst(E e) {
Node<E> x = firstNode;
Node<E> newNode = new Node<>(e, null, x);
if(x ==null) {
firstNode = newNode;
}else {
firstNode.preNode = newNode;
}
size ++;
}

/**
* 向下标index插入元素
* @param index
* @param e
*/
void addBefore(int index, E e) {
if(!checkElementIndex(index)) {
throw new IndexOutOfBoundsException();
}
Node<E> oldNode = getNode(index);
Node<E> preNode = oldNode.preNode;
Node<E> newNode = new Node<>(e, preNode, oldNode);
if(preNode ==null) {
firstNode = newNode;
}else {
preNode.nextNode = newNode;
}
size ++;
}

private Node<E> getNode(int index) {
if(index > (size>>1)) {//从尾部开始查询(二分查找思想)
Node<E> result = lastNode;
for(int i=size-1;i>index;i--) {
result = result.preNode;
}
return result;
}else {//从首部开始查询
Node<E> result = firstNode;
for(int i=0;i<index;i++) {
result = result.nextNode;
}
return result;
}
}

private E unlink(Node<E> e) {
E element = e.item;
Node<E> preNode = e.preNode;
Node<E> nextNode = e.nextNode;
if(preNode ==null) {
firstNode = nextNode;
}else {
preNode.nextNode = nextNode;
e.preNode = null;
}

if(nextNode==null) {
lastNode = preNode;
}else {
nextNode.preNode = preNode;
e.nextNode = null;
}
e.item = null;
size --;
return element;
}

private boolean checkElementIndex(int index) {
if(index <0 || index >=size) {
return false;
}
return true;
}

public static void main(String[] args) {
MyLinkedList<String> myList = new MyLinkedList<String>();
myList.add("String1");
myList.add("String2");
myList.add("String3");
myList.add("String4");
myList.add("String5");
myList.add("String6");
myList.add("String7");
myList.add(3, "2222222222222");
for(int i=0;i<myList.size;i++) {
System.out.println(myList.get(i));
}
System.out.println("===========开始删除下标为3的元素===========");
myList.remove(3);
for(int i=0;i<myList.size;i++) {
System.out.println(myList.get(i));
}
System.out.println("============删除头部元素==========");
myList.removeFirst();
for(int i=0;i<myList.size;i++) {
System.out.println(myList.get(i));
}
System.out.println("==========删除尾部元素============");
myList.removeLast();
for(int i=0;i<myList.size;i++) {
System.out.println(myList.get(i));
}
}
}


三、运行结果
String1

String2

String3

2222222222222

String4

String5

String6

String7

===========开始删除下标为3的元素===========

String1

String2

String3

String4

String5

String6

String7

============删除头部元素==========

String2

String3

String4

String5

String6

String7

==========删除尾部元素============

String2

String3

String4

String5

String6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java LinkedList 原理