java实现简单链表
线性表接口的抽象
package com.fsc.mylinkedlist;
/**
* 线性表操作接口
* @author fsc
*
* @param <T>
*/
public interface ListInterface<T> {
/**
* 向表尾添加元素
*/
public boolean add(T newEntry);
/**
* 向表的指定位置添加元素
*/
public boolean add(T newEntry, int givenPosition);
/**
* 移除指定位置元素
*/
public T remove(int givenPosition);
/**
* 用新元素替换指定位置元素
*/
public T replace(T newEntry, int givenPosition);
/**
* 获取指定位置元素
*/
public T getEntry(int givenPosition);
/**
* 表中是否包含指定元素
*/
public boolean contains(T anEntry);
/**
* 表长
*/
public int getLength();
/**
* 表是否为空
*/
public boolean isEmpty();
/**
* 展示表
*/
public void display();
}
为了插入和删除代码的一致性,引入了哨兵节点(也就是下面代码中出现的firstNode)。
下标的选择和数组的规则相同,都是从0开始。为了满足下标的规则,在代码中相应作出了调整,下面是代码
package com.fsc.mylinkedlist;
public class LList<T> implements ListInterface<T> {
private Node firstNode;
private Node lastNode;
private int length;
public LList() {
clear();
}
/**
* 将链表置为初始状态
*/
public final void clear() {
// firstNode为哨兵节点
firstNode = new Node(null);
lastNode = null;
length = 0;
}
/**
* 向链表尾部插入数据域
*/
@Override
public boolean add(T newEntry) {
return add(newEntry, length);
}
/**
* 向链表指定位置插入数据 position为0时代表向链表头插入元素(第一个元素)
*
* @param newEntry
* @param position
* @return
*/
public boolean add(T newEntry, int position) {
if (newEntry == null) {
throw new IllegalArgumentException("数据域不能为null");
}
if (position < 0 || position > length) {
throw new IllegalArgumentException("插入的位置不合法");
}
Node nextNode = new Node(newEntry);
//向表尾插入的特殊情况处理表尾引用
if(position == length){
if(length == 0){
firstNode.next = nextNode;
lastNode = nextNode;
}else{
lastNode.next = nextNode;
lastNode = nextNode;
}
}else{
// 向currentNode后插入newNode
Node currentNode = getNodeAt(position);
// 插入
nextNode.next = currentNode.next;
currentNode.next = nextNode;
}
length++;
return true;
}
/**
* 删除指定位置的节点 传入0代表删除表头节点
* 链表是从0开始计数
*/
@Override
public T remove(int givenPosition) {
if (givenPosition < 0 || givenPosition >= length) {
throw new IllegalArgumentException("删除的位置不合法");
}
Node currentNode = getNodeAt(givenPosition);
Node result = currentNode.next;
currentNode.next = currentNode.next.next;
return result.data;
}
@Override
public T replace(T newEntry, int givenPosition) {
if (newEntry == null) {
throw new IllegalArgumentException("数据域不能为null");
}
if (givenPosition < 0 || givenPosition >= length) {
throw new IllegalArgumentException("替换的位置不合法");
}
//要替换节点之前的节点
Node currentNode = getNodeAt(givenPosition);
T result = currentNode.next.data;
currentNode.next.data = newEntry;
return result;
}
@Override
public T getEntry(int givenPosition) {
if (givenPosition < 0 || givenPosition >= length) {
throw new IllegalArgumentException("传入的位置不合法");
}
Node currentNode = getNodeAt(givenPosition);
return currentNode.next.data;
}
@Override
public boolean contains(T anEntry) {
if (anEntry == null) {
throw new IllegalArgumentException("数据域不能为null");
}
boolean result = false;
Node currentNode = firstNode.next;
while(currentNode != null){
T data = currentNode.data;
if(anEntry.equals(data)){
result = true;
break;
}
currentNode = currentNode.next;
}
return result;
}
/**
* 从链表的头节点开始打印链表的数据域
*/
@Override
public void display() {
StringBuilder sb = new StringBuilder();
Node currentNode = firstNode.next;
while (currentNode != null) {
sb.append(currentNode.data);
currentNode = currentNode.next;
if (currentNode != null) {
sb.append("->");
}
}
System.out.println(sb.toString());
}
@Override
public int getLength() {
return length;
}
@Override
public boolean isEmpty() {
return length == 0;
}
/**
* 获取指定位置的节点 节点的计数从0开始,getNodeAt(0)代表获取firstNode(哨兵节点)
*
* @param givenPosition
* @return 若要找的位置不存在节点返回null
*/
private Node getNodeAt(int givenPosition) {
// 从头节点向后找
Node currentNode = firstNode;
for (int i = 0; i <= length; ++i) {
if (givenPosition == i) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
/**
* 节点类
*
* @author fsc
*
*/
private class Node {
private T data;
private Node next;
public Node(T data) {
this(data, null);
}
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
}