什么是双向链表
它的组成只是比单链表多了一些指
向前一个节点的前继节点,那么就
是我们对一个节点可以进行两个方
向的操作既前和后其它与单链表一
样。
双向链表的优缺点
优点:
在我们学习单链表的时候还记得我
们是怎么进行节点的删除的么?删
除节点的原理是通过节点指引 (引
用)的变化来进行删除节点, 在单
链表中我们总是需要找到要删除节
点的前继节点而在双向链表我们只
需要找到要删除的节点因为它含有
前继指引(引用)我们就减少寻找前
继节点的步骤。
缺点:
在我们添加节点的时候需要添加前
继节点增加了内存空间。
节点类:
public class DNode {
private int data;
DNode previous;
DNode next;
public DNode(int data,DNode previous,DNode next){
this.data = data;
this.previous = previous;
this.next = next;
}
public int getData(){
return this.data;
}
}
下面我们来看双链表的一些基本操
作,为了方便解释这下方法其实都
在DList类里面但是在这里我为了
方便解释分开了
1.默认在链表尾部插入节点
public class DList {
//默认在链表尾部插入节点
public void insertDNode(int val){
DNode newNode = new DNode(val,null,null);
if(head == null){
head = newNode;
}else{
//寻找尾节点
DNode temp = head;
while(temp.next != null){
temp = temp.next;
}
//将temp的后继指引指向newNode;
temp.next = newNode;
//将newNode的前继指针指向temp;
newNode.previous = temp;
//因为是双向链表索引必须将前继,后继指引设置好才算完整的节点插入
}
}
}
2.指定位置插入节点
//ps:这里的插入是前插入 节点插入位置为5,节点插入后5位置上的是新节点.
public void insertDNode(int val,int position){
DNode newNode = new DNode(val,null,null);
if(head == null){
head = newNode;
}else{
int size = this.Dlength();
if(position < 1 || position > size + 1){
System.out.println("位置不合法");
}
if(position == 1){
newNode.next = head;
head.previous = newNode;
//这里是head更新
head = newNode;
}else{
int count = 1;
DNode fastNode = head;
while( count < size - 1){
fastNode = fastNode.next;
count++;
}
DNode slowNode = fastNode.next;
newNode.next = slowNode;
//截至到目前基本跟单链表的插入基本都一样,如果还不理解可以去看看单链表的那一篇
//解释一下这里为什么需要判断如果slowNode 既是需要删除节点的后继节点不是NULL那么需要设置前继节点
//如果不理解就可以画一下双链表的结构图 感觉链表相关的内容画一下结构图基本都可以掌握理解
if(slowNode != null){
slowNode.previous = newNode;
}
fastNode.next = newNode;//将newNode设为fastNode的后继节点
newNode.previous = fastNode; //将fastNode设为newNode的前继节点
}
}
}
3.删除节点
public void deleteDNode(int position){
if(head == null){
System.out.println("没有什么删除的!!!");
}else{
int size = Dlength();
if(position < 1 || position > size + 1){
System.out.println("The position can not use");
}
if(position == 1){
head = head.next;
head.previous = null;
}else{
int count = 1;
DNode fastNode = head;
//找到删除之前的前继节点
while( count < position - 1){
fastNode = fastNode.next;
count++;
}
//删除位置节点
DNode slowNode = fastNode.next;
//删除位置的后继节点
DNode curNode = slowNode.next;
//变动后继节点next
fastNode.next = curNode;
//判断是否需要前继节点 只要不是NULL都需要设置前继节点
if(curNode != null)
curNode.previous = fastNode;
curNode = null;
}
}
}
4.根据数据删除节点
//这个删除步骤不给出了,你能自己看懂么?
public void deleteNodeByValue(int val){
if(head == null){
System.out.println("都没有!你删什么???");
}else{
DNode temp = head;
while(temp.getData() != val){
temp = temp.next;
}
DNode before = temp.previous;
DNode after = temp.next;
if(after != null){
after.previous = before;
}
before.next = after;
}
}
5.遍历链表,链表长度
//遍历输出链表
public void printALL(){
DNode temp = head;
while(temp != null){
System.out.print(temp.getData()+" ");
temp = temp.next;
}
System.out.println();
}
//链表长度
public int Dlength(){
DNode temp = head;
int le = 0;
while(temp != null){
le++;
temp = temp.next;
}
return le;
}
测试类:
public class TestDNode {
public static void main(String[] args) {
DList list = new DList();
list.insertDNode(5);
list.insertDNode(51);
list.insertDNode(55);
list.insertDNode(25);
list.insertDNode(53);
list.printALL();
list.insertDNode(2, 1);
list.printALL();
list.deleteDNode(3);
list.printALL();
list.insertDNode(66);
list.printALL();
list.deleteNodeByValue(53);
list.printALL();
}
}
输出结果:
5 51 55 25 53
2 5 51 55 25 53
2 5 55 25 53
2 5 55 25 53 66
2 5 55 25 66
上面是双链表的一些基础操作等循
环链表基本操作出完后我打算再写
一篇关于链表的常见问题。我会一
直写这些的让刚接触链表的不要像
我一样很吃力。
嘻嘻~~看完能关注一下么??我的公众号欢迎你们
我的公众号:程序传送门