线性表的接口定义
/**
* 线性表(列表)的接口定义
*/
public interface MyList {
/**
* 新增一个元素
*
* @param element 要新增的那个元素
*/
public void add(Object element);
/**
* 删除相同元素
*
* @param element 要删除的那个元素
*/
void delete(Object element);
/**
* 根据索引删除元素
*
* @param index 要删除元素的索引
*/
void delete(int index);
/**
* 将指定索引位置的元素替换成新元素
*
* @param index 被替换元素的索引
* @param newElement 替换成的新元素
*/
void update(int index, Object newElement);
/**
* 当前列表中是否含有target这个元素
*
* @param target 要查找的元素
* @return 返回是否含有这个元素
*/
boolean contains(Object target);
/**
* 返回指定索引处的元素
*
* @param index 要返回元素的索引
* @return 返回这个元素对象
*/
Object elementAt(int index);
/**
* 查找element所在的索引,如果没有返回-1
* @param element 要查找的元素
* @return 返回元素索引
*/
int indexOf(Object element);
}
双链表的节点定义
public class ListNode {
Object data;
ListNode pre;
ListNode next;
public ListNode(Object data) {
this.data = data;
}
}
双链表的实现类
public class DoubleLinkList implements MyList {
//维护两个首尾结点,这两个结点不用来存储data
private ListNode first = new ListNode(null);
private ListNode last = new ListNode(null);
private int size;
public DoubleLinkList() {
first.next = last;
last.pre = first;
}
/**
* 新增一个元素
*
* @param element 要新增的那个元素
*/
@Override
public void add(Object element) {
ListNode newNode = new ListNode(element);
last.pre.next = newNode;
newNode.next = last;
newNode.pre = last.pre;
last.pre = newNode;
++size;
}
/**
* 删除相同元素
*
* @param element 要删除的那个元素
*/
@Override
public void delete(Object element) {
ListNode p = first.next;
while (p != last) {
if (p.data.equals(element)) {
p.pre.next = p.next;
p.next.pre = p.pre;
//加快被删除结点的回收
p.next = null;
p.pre = null;
--size;
break;
}
p = p.next;
}
}
/**
* 根据索引删除元素
*
* @param index 要删除元素的索引
*/
@Override
public void delete(int index) {
if (index < 0 || index >= size) {
//下标越界,啥也不干
return;
}
//指针指向的节点索引
int i = 0;
ListNode p = first.next;
while (p != last) {
if (i == index) {
//删除p结点
p.pre.next = p.next;
p.next.pre = p.pre;
//加快被删除结点的回收
p.next = null;
p.pre = null;
--size;
break;
}
p = p.next;
++i;
}
}
/**
* 将指定索引位置的元素替换成新元素
*
* @param index 被替换元素的索引
* @param newElement 替换成的新元素
*/
@Override
public void update(int index, Object newElement) {
if (index < 0 || index >= size) {
//下标越界,啥也不干
return;
}
//指针指向的节点索引
int i = 0;
ListNode p = first.next;
while (p != last) {
if (i == index) {
p.data = newElement;
break;
}
p = p.next;
++i;
}
}
/**
* 当前列表中是否含有target这个元素
*
* @param target 要查找的元素
* @return 返回是否含有这个元素
*/
@Override
public boolean contains(Object target) {
ListNode p = first.next;
while (p != last) {
if (p.data.equals(target)) {
return true;
}
p = p.next;
}
return false;
}
/**
* 返回指定索引处的元素
*
* @param index 要返回元素的索引
* @return 返回这个元素对象
*/
@Override
public Object elementAt(int index) {
if (index < 0 || index >= size) {
//下标越界,啥也不干
return null;
}
//指针指向的节点索引
int i = 0;
ListNode p = first.next;
while (p != last) {
if (i == index) {
return p.data;
}
p = p.next;
++i;
}
return null;
}
/**
* 查找element所在的索引,如果没有返回-1
*
* @param element 要查找的元素
* @return 返回元素索引
*/
@Override
public int indexOf(Object element) {
//指针指向的节点索引
int i = 0;
ListNode p = first.next;
while (p != last) {
if (p.data.equals(element)) {
return i;
}
p = p.next;
++i;
}
return -1;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
ListNode p = first.next;
while (p != last) {
sb.append(p.data);
if (p.next != last) {
sb.append(", ");
}
p = p.next;
}
sb.append("]");
return sb.toString();
}
}
测试演示
import org.junit.jupiter.api.Test;
class DoubleLinkedListTest {
@Test
void delete() {
DoubleLinkList list = new DoubleLinkList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
//删除操作之前输出链表元素
System.out.println("删除操作之前输出链表元素: " + list);
list.delete("3");
//删除元素"3"之后输出链表元素
System.out.println("删除元素\"3\"之后输出链表元素: " + list);
//删除下标为0的元素之后输出链表元素
list.delete(0);
System.out.println("删除下标为0的元素之后输出链表元素: " + list);
}
}