我们上次说了,Java实现单向链表,现在我们来实现双向链表。
什么是双向链表,双向链表就是在单向链表的基础上加上一个指向前一个节点的指针,在java中没有指针,那就是一个指向前一个节点地址的对象。
结点的定义就是在单向链表的基础上加一个pre对象。
//定义HeroNode,每个HeroNode 对象就是一个节点
class HeroNode2 {
public int no;
public String name;
public String nickname;
public HeroNode2 next;//指向下一个节点
public HeroNode2 pre;//指向前一个节点
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
然后定义一个双向链表的表头:
//先初始化一个头节点,头节点不能动,不存放具体数据
HeroNode2 head = new HeroNode2(0, "", "");
然后就要实现添加、删除、修改、展示链表和逆向展示链表了。
添加节点:
首先我们实现添加节点了,添加节点就是和单链表的一样,就是通过temp.next==null 找到尾部节点,然后进行插入的时候,让temp.next = node;node.pre = temp;这样就实现了双向链表的添加节点操作。
//添加节点
public void addNode(HeroNode2 node) {
//定义一个临时变量
HeroNode2 temp = head;
while (true) {
//找到队列尾部 temp的位置就是需要插入的位置
if (temp.next == null) {
//需要插入的元素的pre指向 temp 前面的节点
//temp的前一个结点的next 指向需要插入的节点
temp.next = node;
node.pre = temp;
break;
}
temp = temp.next;
}
}
修改节点:
修改节点和单链表一样,首先根据no,找到对应的节点,然后把新的数据赋进去。
//修改节点
public void updateNode(HeroNode2 node) {
HeroNode2 temp = head;
while (true) {
if (head.next == null) {
System.out.println("空链表~");
break;
}
if (temp.next == null) {
System.out.println("该节点不存在~");
}
if (temp.next.no == node.no) {
temp.next.name = node.name;
temp.next.nickname = node.nickname;
break;
}
temp = temp.next;
}
}
删除节点:
删除节点算是变化最大的地方,我们根据no找到需要删除的节点temp,然后只需要让temp.pre.next指向temp.next,让temp.next.pre指向temp.pre,这样就把需要删除的节点从链表中删除了。
//删除节点
public void deleteNode(int no){
HeroNode2 temp = head;
while (true) {
temp = temp.next;
if (head.next == null) {
System.out.println("空链表~");
break;
}
if (temp == null) {
System.out.println("该节点不存在~");
}
if (temp.no == no) {
temp.next.pre = temp.pre;
temp.pre.next = temp.next;
break;
}
}
}
展示链表:
依旧和单向链表一样,遍历到.next不为null的就输出。
//展示链表
public void showNode() {
//临时变量
HeroNode2 temp = head;
while (true) {
if (temp.next == null) {
break;
}
System.out.println(temp.next);
temp = temp.next;
}
}
逆向展示链表:
逆向展示链表,在单向链表中也可以实现,只不过你得从新定义一个头节点,然后从原链表中一个一个摘过来,浪费空间,且操作麻烦,最重要的是破环了原来的链表,而在双向链表中,我们只需要判断让临时节点temp走到最后一个节点,然后让节点输出,并temp=temp.pre即可实现,简单方便。
//倒序输出
public void showReverseOrder(){
HeroNode2 temp = head;
if (head.next == null){
System.out.println("空链表~");
}
while (true){
if (temp.next==null){
break;
}
temp = temp.next;
}
while (temp.pre != null){
System.out.println(temp);
temp = temp.pre;
}
}
最后我们测试一下。
public static void main(String[] args) {
//创建链表
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
//创建英雄
HeroNode2 hero1 = new HeroNode2(1, "疾风剑豪", "亚索");
HeroNode2 hero2 = new HeroNode2(2, "无双剑姬", "菲奥娜");
HeroNode2 hero3 = new HeroNode2(3, "无极剑圣", "易");
HeroNode2 hero4 = new HeroNode2(4, "暗裔剑魔", "亚托克斯");
doubleLinkedList.addNode(hero1);
doubleLinkedList.addNode(hero2);
doubleLinkedList.addNode(hero3);
doubleLinkedList.addNode(hero4);
doubleLinkedList.showNode();
System.out.println("--------------------------------");
doubleLinkedList.updateNode(new HeroNode2(3,"迷失之牙","纳尔"));
doubleLinkedList.showNode();
System.out.println("--------------------------------");
doubleLinkedList.showReverseOrder();
System.out.println("--------------------------------");
doubleLinkedList.deleteNode(3);
doubleLinkedList.showNode();
System.out.println("--------------------------------");
}
测试结果为:
HeroNode{no=1, name='疾风剑豪', nickname='亚索'}
HeroNode{no=2, name='无双剑姬', nickname='菲奥娜'}
HeroNode{no=3, name='无极剑圣', nickname='易'}
HeroNode{no=4, name='暗裔剑魔', nickname='亚托克斯'}
--------------------------------
HeroNode{no=1, name='疾风剑豪', nickname='亚索'}
HeroNode{no=2, name='无双剑姬', nickname='菲奥娜'}
HeroNode{no=3, name='迷失之牙', nickname='纳尔'}
HeroNode{no=4, name='暗裔剑魔', nickname='亚托克斯'}
--------------------------------
HeroNode{no=4, name='暗裔剑魔', nickname='亚托克斯'}
HeroNode{no=3, name='迷失之牙', nickname='纳尔'}
HeroNode{no=2, name='无双剑姬', nickname='菲奥娜'}
HeroNode{no=1, name='疾风剑豪', nickname='亚索'}
--------------------------------
HeroNode{no=1, name='疾风剑豪', nickname='亚索'}
HeroNode{no=2, name='无双剑姬', nickname='菲奥娜'}
HeroNode{no=4, name='暗裔剑魔', nickname='亚托克斯'}
--------------------------------
进程已结束,退出代码为 0
成功实现。
源代码:
public class DoubleLinkedListDemo {
public static void main(String[] args) {
//创建链表
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
//创建英雄
HeroNode2 hero1 = new HeroNode2(1, "疾风剑豪", "亚索");
HeroNode2 hero2 = new HeroNode2(2, "无双剑姬", "菲奥娜");
HeroNode2 hero3 = new HeroNode2(3, "无极剑圣", "易");
HeroNode2 hero4 = new HeroNode2(4, "暗裔剑魔", "亚托克斯");
doubleLinkedList.addNode(hero1);
doubleLinkedList.addNode(hero2);
doubleLinkedList.addNode(hero3);
doubleLinkedList.addNode(hero4);
doubleLinkedList.showNode();
System.out.println("--------------------------------");
doubleLinkedList.updateNode(new HeroNode2(3,"迷失之牙","纳尔"));
doubleLinkedList.showNode();
System.out.println("--------------------------------");
doubleLinkedList.showReverseOrder();
System.out.println("--------------------------------");
doubleLinkedList.deleteNode(3);
doubleLinkedList.showNode();
System.out.println("--------------------------------");
}
}
//双向链表
class DoubleLinkedList {
//先初始化一个头节点,头节点不能动,不存放具体数据
HeroNode2 head = new HeroNode2(0, "", "");
//返回头节点
public HeroNode2 getHead() {
return head;
}
//添加节点
public void addNode(HeroNode2 node) {
//定义一个临时变量
HeroNode2 temp = head;
while (true) {
//找到队列尾部 temp的位置就是需要插入的位置
if (temp.next == null) {
//需要插入的元素的pre指向 temp 前面的节点
//temp的前一个结点的next 指向需要插入的节点
temp.next = node;
node.pre = temp;
break;
}
temp = temp.next;
}
}
//展示链表
public void showNode() {
//临时变量
HeroNode2 temp = head;
while (true) {
if (temp.next == null) {
break;
}
System.out.println(temp.next);
temp = temp.next;
}
}
//修改节点
public void updateNode(HeroNode2 node) {
HeroNode2 temp = head;
while (true) {
if (head.next == null) {
System.out.println("空链表~");
break;
}
if (temp.next == null) {
System.out.println("该节点不存在~");
}
if (temp.next.no == node.no) {
temp.next.name = node.name;
temp.next.nickname = node.nickname;
break;
}
temp = temp.next;
}
}
//删除节点
public void deleteNode(int no){
HeroNode2 temp = head;
while (true) {
temp = temp.next;
if (head.next == null) {
System.out.println("空链表~");
break;
}
if (temp == null) {
System.out.println("该节点不存在~");
}
if (temp.no == no) {
temp.next.pre = temp.pre;
temp.pre.next = temp.next;
break;
}
}
}
//倒序输出
public void showReverseOrder(){
HeroNode2 temp = head;
if (head.next == null){
System.out.println("空链表~");
}
while (true){
if (temp.next==null){
break;
}
temp = temp.next;
}
while (temp.pre != null){
System.out.println(temp);
temp = temp.pre;
}
}
}
//定义HeroNode,每个HeroNode 对象就是一个节点
class HeroNode2 {
public int no;
public String name;
public String nickname;
public HeroNode2 next;//指向下一个节点
public HeroNode2 pre;//指向前一个节点
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}