双链表实现增删查改基础操作
//Sequence.java
public interface Sequence {//接口
/**
* 向线性表中添加元素
* @param data 要存储的元素
*/
void add(Object data);
/**
* 线性表中删除元素
* @param index 要删除的元素下标
* @return 是否删除成功
*/
boolean remove(int index);
/**
* 在线性表中查找指定索引的元素
* @param index 要查找的索引
* @return
*/
Object get(int index);
/**
* 判断线性表中是否有指定元素
* @param data 要查找的元素内容
* @return
*/
boolean contains(Object data);
/**
* 修改线性表中指定索引的内容
* @param index 要修改的元素下标
* @param newData 修改后的内容
* @return
*/
Object set(int index,Object newData);
/**
* 返回当前线性表元素个数
* @return
*/
int size();
/**
* 直接清空线性表内容
*/
void clear();
/**
* 将线性表转为数组
* @return
*/
Object[] toArray();
}
//DoubleLinkList.java
public class DoubleLinkList implements Sequence{//类实现接口(小彩蛋 覆写接口所有类的快捷方法为:将光标放置本行Sequence后,按ALT+ENTER键一路向下即可)
private Node head;//头节点
private Node tail;//尾节点
private int size;//链表长度
class Node{//节点类
Node prev;//前驱指针
Object data;//数据
Node next;//后继指针
public Node(Node prev, Object data, Node next) {
this.prev = prev;
this.data = data;
this.next = next;
}
public Node(Object data) {
this.data = data;
}
}
public void add(Object data){//增加操作(采用尾插法)
Node newNode=new Node(tail,data,null);
if(head==null){
head=newNode;
}else {
tail.next=newNode;
}
tail=newNode;
size++;
}
@Override
public boolean remove(int index) {//删除操作
if(head==null){
return false;
}
rangeCheck(index);//判断下标是否合理
Node cur=node(index);//确定当前下标节点
Node next=cur.next;//当前节点后继指针
Node prev=cur.prev;//当前节点前驱指针
//删除节点最复杂情况为删除中间节点(即需要重新调整四个指针关系),故先看左边再看右边判断
if(prev==null){
head=next;
}else{
prev.next=next;
prev=null;
}
if(next==null){
tail=prev;
}else{
next.prev=prev;
next=null;
}
size--;
return false;
}
@Override
public Object get(int index) {//获得特定下标节点
rangeCheck(index);
return node(index).data;//返回节点数据
}
@Override
public boolean contains(Object data) {//查看链表中是否有特定元素
if(head==null){
return false;
}
Object[] array=toArray();
for(int i=0;i<array.length;i++){
if(array[i]==data){
return true;
}
}
return false;
}
@Override
public Object set(int index, Object newData) {//替换特定节点元素,并返回原节点数据
rangeCheck(index);
Node node=node(index);
Object oldData=node.data;
node.data=newData;
return oldData;
}
@Override
public int size() {//链表长度
return this.size;
}
@Override
public void clear() {//清空
for(Node temp=head;temp!=null;temp=temp.next){
if(head.next!=null){//判断是否下一个节点为空
head=head.next;//先将头节点移动至下一节点,保证后面节点存在
temp.data=null;
}else{//若为空则只有一个节点(置空数据即可,因头节点前驱指针本来就指向Null,尾节点后继节点也如此)
head.data=null;
}
size--;
}
}
@Override
public Object[] toArray() {//链表转变为数组
Object[] data=new Object[size];
int i=0;
for(Node temp=head;temp!=null;temp=temp.next){
data[i++]=temp.data;
}
return data;
}
private void rangeCheck(int index){//判断下标是否合理
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下标越界异常");
}
}
private Node node(int index){//采用从前到后或从后到前的方法寻找某下标节点
//查找指定下标节点,因双链表可从前至后遍历也可从后至前遍历,故我们可从中间下标划分,之前的从前至后遍历,之后的从后至前遍历,减少遍历次数
if(index<size>>1){
Node cul=head;
for(int i=0;i<index;i++){
cul=cul.next;
}
return cul;
}else{
Node cull=tail;
for(int i=size-1;i>index;i--){
cull=cull.prev;
}
return cull;
}
}
public void display(){
for(Node temp=head;temp!=null;temp=temp.next){
System.out.print(temp.data+" ");
}
}
}
//Test.java
public class Test {
public static void main(String[] args) {
DoubleLinkList doubleLinkList=new DoubleLinkList();
doubleLinkList.add(1);
doubleLinkList.add(2);
doubleLinkList.add(3);
doubleLinkList.add(4);
doubleLinkList.add(5);
doubleLinkList.display();//增加节点输出
System.out.println();
System.out.println(doubleLinkList.size());//测试链表长度
System.out.println("-----------------------");
System.out.println(doubleLinkList.get(1));//测试取得指定下标节点
System.out.println(doubleLinkList.get(3));
System.out.println("-----------------------");
System.out.println(doubleLinkList.get(1));
doubleLinkList.set(1,100);//替换指定下标节点数据
System.out.println(doubleLinkList.get(1));//测试是否替换成功
System.out.println("-----------------------");
doubleLinkList.remove(0);//移除指定下标节点
System.out.println(doubleLinkList.size());//测试是否移除成功
System.out.println("-----------------------");
System.out.println(doubleLinkList.contains(3));//测试链表中是否存在指定数据
System.out.println(doubleLinkList.contains(90));
System.out.println("-----------------------");
doubleLinkList.clear();//清空
System.out.println(doubleLinkList.size());//测试是否清空
}
}
添加节点图解:
删除节点图解:
运行结果: