前面我们讲过,链表是一种很好的数据存储方式,对于数据的插入和删除效率都很高,一般我们常用的是jdk里的链表,很多人用的虽多,却不一定都熟悉具体的写法和逻辑,而且jdk为了兼容性更好,难免在效率上进行妥协,如果你对性能有很高的要求,不妨根据自己的需求去手动实现一个链表。
第一步:首先创建一个节点内部类
/**
* 节点
*/
private static class Node<E>{
E item; //当前节点
Node<E> prev; //前一个节点
Node<E> next; //后一个节点
public Node(Node<E> prev,E item , Node<E> next) {
this.item = item;
this.prev = prev;
this.next = next;
}
}
第二部:我们创建无参的构造方法,和声名头尾节点,以及链表大小
//头节点
Node<E> first;
//尾节点
Node<E> last;
//大小
int size;
第三部:加入我们需要的方法函数,比如添加方法,删除方法
1.末尾添加数据
/**
* 添加数据在最后
*/
public void add(E e){
linkLast(e);
}
/**
* 添加到最后
* @param e
*/
public void linkLast(E e){
Node<E> newNode=new Node<E>(last,e,null);
Node<E> l=last;
last=newNode;
if(l==null){
first=newNode;
}else {
l.next = newNode;
}
size++;
}
2.获取当前节点
/**
* 获得当前位置的节点
* @param index
* @return
*/
public E get(int index){
if(index<0 || index>size){
return null;
}
return node(index).item;
}
/**
* 获取index位置上的节点
* @param index
* @return
*/
private Node<E> node(int index) {
//如果index在整个链表前半部分
if(index < (size/2)) {
Node<E> node=first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}else {
Node<E> node=last;
for (int i = size-1; i > index; i--) {
node = node.prev;
}
return node;
}
}
3.指定位置添加
/**
* 添加数据在指定位置
* @param index
* @param e
*/
public void add(int index,E e){
if(index<0 || index>size){
return;
}
if(size == index) {
linkLast(e);
}else {
Node<E> targe = node(index);
Node<E> pre = targe.prev;
Node<E> newNode = new Node<>(pre,e,targe);
if(pre==null){ //如果前缀为null
first=newNode;
targe.prev = newNode;
}else {
pre.next = newNode;
targe.prev = newNode;
}
size++;
}
}
4.指定位置删除
/**
* 删除指定节点
* @param index
*/
public void remove(int index){
Node<E> target=node(index);
unLinkNode(target);
}
private void unLinkNode(Node<E> p) {
Node<E> pre=p.prev;
Node<E> next=p.next;
if(pre==null){ //删除无前缀的点
first=p.next;
}else {
pre.next=p.prev;
}
if(next==null){ //删除无后缀的点
last=p.prev;
}else {
next.prev=p.prev;
}
size--;
}
5.清空链表
/**
* 清空链表
*/
public void clear(){
for(Node<E> x = first; x != null;){
Node<E> next = x.next;
x.item = null;
x.prev = null;
x.next = null;
x = next;
}
first = last = null;
size = 0;
}
以上就是一些常用的方法函数,当然如果有更多的需求,可以自行添加,下面展示完整代码
public class LinkedList<E> {
/**
* 节点内部类
*/
private static class Node<E>{
E item; //当前节点
Node<E> prev; //前一个节点
Node<E> next; //后一个节点
public Node(Node<E> prev,E item , Node<E> next) {
this.item = item;
this.prev = prev;
this.next = next;
}
}
public LinkedList(){
}
//头节点
Node<E> first;
//尾节点
Node<E> last;
//大小
int size;
/**
* 添加数据在最后
*/
public void add(E e){
linkLast(e);
}
/**
* 添加到最后
* @param e
*/
public void linkLast(E e){
Node<E> newNode=new Node<E>(last,e,null);
Node<E> l=last;
last=newNode;
if(l==null){
first=newNode;
}else {
l.next = newNode;
}
size++;
}
/**
* 获得当前位置的节点
* @param index
* @return
*/
public E get(int index){
if(index<0 || index>size){
return null;
}
return node(index).item;
}
/**
* 获取index位置上的节点
* @param index
* @return
*/
private Node<E> node(int index) {
//如果index在整个链表前半部分
if(index < (size>>1 )) {
Node<E> node=first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}else {
Node<E> node=last;
for (int i = size-1; i > index; i--) {
node = node.prev;
}
return node;
}
}
/**
* 添加数据在指定位置
* @param index
* @param e
*/
public void add(int index,E e){
if(index<0 || index>size){
return;
}
if(size == index) {
linkLast(e);
}else {
Node<E> targe = node(index);
Node<E> pre = targe.prev;
Node<E> newNode = new Node<>(pre,e,targe);
if(pre==null){ //如果前缀为null
first=newNode;
targe.prev = newNode;
}else {
pre.next = newNode;
targe.prev = newNode;
}
size++;
}
}
/**
* 删除指定节点
* @param index
*/
public void remove(int index){
Node<E> target=node(index);
unLinkNode(target);
}
private void unLinkNode(Node<E> p) {
Node<E> pre=p.prev;
Node<E> next=p.next;
if(pre==null){ //删除无前缀的点
first=p.next;
}else {
pre.next=p.prev;
}
if(next==null){ //删除无后缀的点
last=p.prev;
}else {
next.prev=p.prev;
}
size--;
}
/**
* 清空链表
*/
public void clear(){
for(Node<E> x = first; x != null;){
Node<E> next = x.next;
x.item = null;
x.prev = null;
x.next = null;
x = next;
}
first = last = null;
size = 0;
}
}