双向链表优缺点:
双向链表:有两个指针,一个指向前一个节点,一个后一个节点。
优点:与单向链表相比,可以找到前驱和后继,可进可退;
缺点:增加删除节点复杂,需要多分配一个指针存储空间。
适用于需要双向查找节点值的情况。
代码实现
package linkedlist;
import org.junit.Test;
/**
* 双向链表
* @author
* @create 2020-07-16 6:16 PM
*/
public class DubboLinkedListDemo {
@Test
public void testAdd(){
DubboLinkedList dubboLinkedList = new DubboLinkedList();
dubboLinkedList.add(new Student(1,"zs"));
dubboLinkedList.add(new Student(4,"zl"));
dubboLinkedList.add(new Student(2,"ls"));
dubboLinkedList.add(new Student(3,"ww"));
dubboLinkedList.showDubboLinkedList();
}
@Test
public void testAddByOrder(){
DubboLinkedList dubboLinkedList = new DubboLinkedList();
dubboLinkedList.addByOrder(new Student(1,"zs"));
dubboLinkedList.addByOrder(new Student(4,"zl"));
dubboLinkedList.addByOrder(new Student(2,"ls"));
dubboLinkedList.addByOrder(new Student(3,"ww"));
dubboLinkedList.showDubboLinkedList();
}
@Test
public void testUpdate(){
DubboLinkedList dubboLinkedList = new DubboLinkedList();
dubboLinkedList.add(new Student(1,"zs"));
dubboLinkedList.add(new Student(4,"zl"));
dubboLinkedList.add(new Student(2,"ls"));
dubboLinkedList.add(new Student(3,"ww"));
System.out.println("修改前~~~");
dubboLinkedList.showDubboLinkedList();
dubboLinkedList.update(new Student(1,"张三"));
System.out.println("修改后~~~");
dubboLinkedList.showDubboLinkedList();
}
@Test
public void testDel(){
DubboLinkedList dubboLinkedList = new DubboLinkedList();
dubboLinkedList.add(new Student(1,"zs"));
dubboLinkedList.add(new Student(4,"zl"));
dubboLinkedList.add(new Student(2,"ls"));
dubboLinkedList.add(new Student(3,"ww"));
System.out.println("删除前~~~");
dubboLinkedList.showDubboLinkedList();
dubboLinkedList.del(4);
System.out.println("删除后~~~");
dubboLinkedList.showDubboLinkedList();
}
}
class DubboLinkedList{
//创建头节点,头节点不存放任何数据,只用来表示链表的头部.在对链表的操作中,头部节点保持不动
private Student headNode = new Student(0,"");
public Student getHeadNode() {
return headNode;
}
//遍历链表(双向链表可以从前往后遍历,也可以从后往前遍历)
public void showDubboLinkedList(){
if(headNode.next==null){
System.out.println("链表为空~~~");
return;
}
Student temp = headNode.next;
while (true){
if(temp==null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
/**
* 添加(追加在链表尾部)
* 分析:
* 遍历链表,找到链表的最后一个节点,在后面追加即可。
* temp.next = newNode;
* newNode.pre = temp;
* @param newNode
*/
public void add(Student newNode){
Student temp = headNode;
while (true){
if(temp.next==null){
break;
}
temp = temp.next;
}
temp.next = newNode;
newNode.pre = temp;
}
/**
* 带排序的添加
* 分析:
* 遍历链表,找到要添加节点的位置
* temp = head
* 从head后面的第一个节点开始(temp.next)对比,如果其sno>newNode,则找到位置。记录这个temp
* 插入节点的位置在temp后面。
* 1)如果插入的位置在链表的中间,连接新节点的next 和 pre
* newNode.next = temp.next
* temp.next.pre = newNode
* temp.next = newNode
* newNode.pre = temp
*
* 2)如果找到的位置在链表尾部,则直接追加到链表后面
* temp.next = newNode;
* newNode.pre = temp
* @param newNode
*/
public void addByOrder(Student newNode){
Student temp =headNode;
boolean flag = false; //是否存在学号相同的节点
while(true){
if(temp.next==null){
break;
}
if(temp.next.sno>newNode.sno){
break;
}
if(temp.next.sno==newNode.sno){
flag=true;
break;
}
temp = temp.next;
}
if(flag){
System.out.println("已经存在相同学号的学生了。。。");
return;
}else{
if(temp.next!=null){
temp.next.pre = newNode;
}
newNode.next = temp.next;
temp.next = newNode;
newNode.pre = temp;
}
}
/**
* 修改节点
* 找到要修改的节点,直接修改
* @param node
*/
public void update(Student node){
if(headNode.next==null){
System.out.println("链表为空~~~");
return;
}
Student temp = headNode.next;
boolean flag = false;//是否找到要修改的节点
while (true){
if(temp==null){//已经遍历了整个链表,也没有找到要修改的节点。
break;
}
if(temp.sno == node.sno){
flag= true;
break;
}
temp = temp.next;
}
if(flag){
temp.sname = node.sname;
}else{
System.out.println("链表中没有学号为【"+node.sno+"】的节点,无法修改");
}
}
/**
* 删除
* 分析:
* 遍历链表,找到要删除的节点。
* temp.pre.next = temp.next
* temp.next.pre = temp.pre
* tips:单链表要删除节点,需要找到被删除节点的前一个节点,而双向链表删除节点,找到被删除节点即可。
* @param sno
*/
public void del(int sno){
if(headNode.next==null){
System.out.println("链表为空~~~");
return;
}
Student temp = headNode.next;
boolean flag = false;//是否找到要删除的节点
while(true){
if(temp==null){
break;
}
if(temp.sno == sno){
flag=true;
break;
}
temp = temp.next;
}
if(flag){
temp.pre.next = temp.next;
if(temp.next!=null){
temp.next.pre = temp.pre;
}
}else{
System.out.println("链表中没有学号为【"+sno+"】的节点,无法删除");
}
}
}
class Student{
public int sno;
public String sname;
public Student next;
public Student pre;
public Student() {
}
public Student(int sno, String sname) {
this.sno = sno;
this.sname = sname;
}
@Override
public String toString() {
return "Student{" +
"sno=" + sno +
", sname='" + sname + '\'' +
'}';
}
}