版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HeadingAlong/article/details/54783321
在上篇博客当中介绍单链表的实现。在单链表的基础上设计双链表并不会太难,只需要理解双链表的结构,是如何进行数据操作的,即可完成代码的设计。
何为双链表
双链表的每个数据节点中都有两个引用,分别指向前一个节点和后一个节点。所以,从双向链表中的任意一个结点开始,都可以方便的进行数据查找。
代码实现
注意:该链表同样不允许放入相同元素
- 双链表的节点
class Node{
//节点属性
private T date;
private Node next;
private Node prev;
public Node(T date){
this.date = date;
}
}
- 从尾部添加数据 addLast
public boolean addLast(T date){
boolean flag = false;
if(!existNode(date)){
//将数据封装为节点添加进来
Node newNode = new Node(date);//新建新节点
//判断链表有没有数据
if(head==null){//说明链表为空
//直接将新节点作为头结点和尾节点
head = newNode;
tail = newNode;
}else{//链表不为空,从尾部开始添加
//新节点的prev指向尾节点,
newNode.prev = tail;
//尾节点的next指向新节点
tail.next = newNode;
//将尾节点指向新建节点
tail = newNode;
}
flag = true;
}
return flag;
}
- 从头添加数据 addFirst
public boolean addFirst(T date){
boolean flag = false;
if(!existNode(date)){//确定链表中没有即将添加的节点
//将数据封装为节点添加进来
Node newNode = new Node(date);//新建新节点
//判断链表有没有数据
if(head==null){//说明链表为空
//直接将新节点作为头结点和尾节点
head = newNode;
tail = newNode;
}else{//链表不为空,从头部开始添加
//新节点的prev置为null
newNode.prev = null;
//新节点的next指向头结点
newNode.next = head;
//将头节点指向新建节点
head = newNode;
}
flag = true;
}else{
throw new RuntimeException("数据在链表中已经存在!");
}
return flag;
}
- 有序添加数据
public boolean addOrdered(T date){
boolean flag = false;
//确认链表中没有该数据
if(!existNode(date)){
//找到比该链表大的节点
Node biggerNode = findBiggerNode(date);
if(biggerNode==null){//没有找到比新节点大的节点
//将该节点添加在尾部
this.addLast(date);
}else{//找到了比该节点大的节点,将该节点放在大节点的前面
Node prev = biggerNode.prev;//找到大节点前面的节点
if(prev==null){//前面节点为空,说明该大节点是头结点,将新节点从头添加
addFirst(date);
}else{//前面节点不为空,
Node newNode = new Node(date);//创建新节点
prev.next = newNode;//将前面节点的next指向新节点
newNode.prev = prev;//将新节点的prev指向前面节点
newNode.next = biggerNode;//将新节点的next指向大节点
biggerNode.prev = newNode;//将大节点的prev指向新节点
}
}
flag = true;
}
return flag;
}
- 更新数据 update
public boolean update(T old,T newDate){
boolean flag = false;
Node target = findNode(old);//找到要更新的节点(此时拿到的是节点的引用)
if(target==null){
throw new RuntimeException("没有此数据");
}else{//确定节点已经存在
Node existNode = findNode(newDate);
if(existNode!=null){//确定数据唯一
throw new RuntimeException("该数据已经存在,请使用不存在的数据");
}
//修改该数据的date值
target.date = newDate;
flag = true;
}
return flag;
}
- 删除数据 remove
public boolean remove(T date){
boolean flag = false;
//找到该节点
Node target = findNode(date);
try {
if(target!=null){
if(target.next==null&&target.prev==null){//既是头结点又是尾节点
head = null;
tail = null;
}
else if(target.next == null){//说明该节点是尾节点
//将该节点的上一个节点的next置为null
target.prev.next = null;
//将该节点的上一个节点作为尾节点
tail = target.prev;
}else if(target.prev == null){//说明该节点是头节点
//将该节点的下一个节点的prev置为null
target.next.prev = null;
//将该节点的下一个节点作为头结点
head = target.next;
}else{//该节点是中间节点
//将该节点的next节点的prev指向该节点的prev节点
target.next.prev = target.prev;
//将该节点的prev节点的next指向该节点的next节点
target.prev.next = target.next;
}
flag = true;
}
} catch (Exception e) {
throw new RuntimeException("元素不存在");
}
return flag;
}