本链表值实现基本的增删查改功能,可以在符合逻辑情况下增加其他方法
一.接口的实现
可以将链表的代码放在接口中,便于阅读链表方法和随时增删查改部分功能,而且只要实现了该接口可以对方法进行重写实现
public interface SingleLinkedList {
//------------------------------------增-----------------------------
//头插
void addFirst(int value);
//尾插
void addEnd(int value);
//中插
void addIndex(int pos,int value);
//------------------------------------删-----------------------------
//删除遇到的第一个该元素
void remove(int value);
//删除全部该元素
void removeAll(int value);
//------------------------------------查-----------------------------
//查找某个元素是否存在
boolean contains(int key);
//------------------------------------改-----------------------------
//将某个元素改值
void set(int key,int value);
//------------------------------------其他-----------------------------
//统计链表长度
int size();
//清空链表
void clear();
//打印链表
void display();
}
二.代码实现
内部类:
当⼀个事物的内部,还有⼀个部分需要⼀个完整的结构进⾏描述,⽽这个内部的完整的结构⼜只为外部事物提供服务,那么这个内部的完整结构最好使⽤内部类
而这里链表的实现需要结点,而结点是个完整的结构又为链表提供服务,可以定义内部类
public class MyDLinkedList implements DLinkedList {
static class DListNode {
public int value;
//存储前一个结点的引用
public DListNode prev;
public DListNode next;
public DListNode(int value) {
this.value = value;
}
}
//存储第一个结点 左后一个结点的引用
public DListNode pHead;
public DListNode pLast;
//---------------------------------------------增---------------
@Override
public void addFirst(int value) {
DListNode dListNode = new DListNode(value);
if(pHead == null){
pHead = pLast = dListNode;
return;
}
dListNode.next = pHead;
pHead.prev = dListNode;
pHead = pHead.prev;
}
@Override
public void addEnd(int value) {
DListNode dListNode = new DListNode(value);
if(pHead == null){
pHead = pLast = dListNode;
return;
}
pLast.next = dListNode;
dListNode.prev = pLast;
pLast = pLast.next;
}
//检查pos位置是否合理(这里建议引异常)
private void checkPosIllegality(int pos){
if(pos < 0 || pos >this.size()){
throw new PosIllegalityException("addIndex方法下标异常>:"+pos);
}
}
// 寻找下标的位置
private DListNode searchPosReturnNode(int pos){
DListNode cur = pHead;
while(pos != 0){
cur = cur.next;
pos--;
}
return cur;
}
@Override
public void addIndex(int pos, int value) {
DListNode dListNode = new DListNode(value);
// 1.检查pos位置是否合理(这里建议引异常)
checkPosIllegality(pos);
if(pos == 0){
this.addFirst(value);
return;
}
// 2.寻找下标的位置
DListNode posReturnNode = searchPosReturnNode(pos);
//这里注意,双向链表当前位置能找到前一个元素,
// 所以 posReturnNode 可能为null,此时 .prev就会出错
// 3.判断
if(posReturnNode == null){
this.addEnd(value);
return;
}
// 4.插入
posReturnNode.prev.next = dListNode;
dListNode.prev = posReturnNode.prev;
dListNode.next = posReturnNode;
posReturnNode.prev = dListNode;
}
//---------------------------------------------删---------------
//寻找元素
private DListNode searchElemReturnNode(int key){
DListNode cur = pHead;
while(cur != null){
if(cur.value == key){
return cur;
}
cur = cur.next;
}
return null;
}
@Override
public void remove(int key) {
if(pHead == null){
System.out.println("链表为空");
return;
}
DListNode cur = pHead;
while(cur != null){
// 判断是否相等
if(cur.value == key){
//判断是否为第一个结点
if(cur == pHead){
// pHead 向后移
pHead = pHead.next;
//这里注意 链表 可能只有一个节点
//为 null 不管
//不为空 则把 Phead 的 prev置为 null
if(pHead != null){
pHead.prev = null;
}
}else{
cur.prev.next = cur.next;
// 判断 是否为最后一个结点
if(cur.next == null){
pLast = pLast.prev;
// cur.prev.next = cur.next;
}else{
//否则 就是删除中间的结点
// cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}
}
//删除了就退出
return;
}
cur = cur.next;
}
}
@Override
public void removeAll(int key) {
if(pHead == null){
System.out.println("链表为空");
return;
}
DListNode cur = pHead;
while(cur != null){
// 判断是否相等
if(cur.value == key){
//开始删除
//判断是否为第一个结点
if(cur == pHead){
// pHead 向后移
pHead = pHead.next;
//这里注意 链表 可能只有一个节点
//为 null 不管
//不为空 则把 Phead 的 prev置为 null
if(pHead != null){
pHead.prev = null;
}
}else{
cur.prev.next = cur.next;
// 判断 是否为最后一个结点
if(cur.next == null){
pLast = pLast.prev;
// cur.prev.next = cur.next;
}else{
//否则 就是删除中间的结点
// cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}
}
}
cur = cur.next;
}
}
//---------------------------------------------查---------------
@Override
public boolean contains(int value) {
if(pHead != null){
return false;
}
DListNode cur = pHead;
while(cur != cur){
if(cur.value == value){
return true;
}
cur = cur.next;
}
return false;
}
//---------------------------------------------改---------------
private void checkSetPosIllegality(int pos){
if(pos < 0 || pos >=this.size()){
throw new PosIllegalityException("set方法下标不合理"+pos);
}
}
@Override
public void set(int pos, int value) {
// 判断下标异常
checkSetPosIllegality(pos);
// 找到下标的结点
DListNode cur = pHead;
while(pos != 0){
cur = cur.next;
pos--;
}
cur.value = value;
}
//--------------------------------------------其他---------------
@Override
public int size() {
int count = 0;
DListNode cur = pHead;
while(cur != null){
count++;
cur = cur.next;
}
return count;
}
@Override
public void clear() {
//仿照单链表的清除
DListNode cur = pHead;
while(cur != null){
DListNode curN = cur.next;
cur.value = 0;
cur.prev = null;
cur.next = null;
cur = curN;
}
pHead = pLast = null;
}
@Override
public void display() {
DListNode cur = pHead;
while(cur != null){
System.out.print(cur.value+"-->");
cur = cur.next;
}
System.out.print("null");
}
}
这里检查下标pos的合法性,要引入异常:
public class SingListPosIllegality extends RuntimeException {
public SingListPosIllegality() {
}
public SingListPosIllegality(String message) {
super(message);
}
}
三.运行
1.运行该代码
public class test {
public static void main(String[] args) {
MyDLinkedList myDLinkedList = new MyDLinkedList();
//尾插
myDLinkedList.addEnd(1);
myDLinkedList.addEnd(2);
myDLinkedList.addEnd(3);
myDLinkedList.addEnd(4);
myDLinkedList.addEnd(5);
myDLinkedList.display();
//头插
myDLinkedList.addFirst(1);
myDLinkedList.addFirst(2);
myDLinkedList.addFirst(3);
myDLinkedList.addFirst(4);
myDLinkedList.addFirst(5);
myDLinkedList.display();
//中插
System.out.println();
myDLinkedList.addIndex(2,10086);
myDLinkedList.display();
//移除
System.out.println();
myDLinkedList.remove(4);
myDLinkedList.display();
//移除全部
System.out.println();
myDLinkedList.removeAll(4);
myDLinkedList.display();
//判断某个元素是否存在
System.out.println();
System.out.print(myDLinkedList.contains(6));
//修改下标的值
System.out.println();
myDLinkedList.set(2,10000);
myDLinkedList.display();
myDLinkedList.clear();
}
}