双向链表(JAVA实现)

双向链表与单链表的对比:
1、单向链表查找只能是一个方向,双向链表可以向前或者向后查找
2、单向链表不能自我删除,需要靠辅助节点**(即需要通过找到要删除的节点的前一个节点,通过该节点进行删除的操作,而双向链表只需找到要删除的节点就行了)**。双向链表可以自我删除

双向链表示意图
在这里插入图片描述

分析(代码实现原理):temp为辅助节点(因为头节点不可动)
1、遍历:方式与单链表一致,但是是双向的,可以向前,也可以向后
2、添加(默认添加到最后面)
(1)先找到链表的最后一个节点
(2)temp.next=newnode
(3)newnode.pre=temp
3、修改:思路与原理与单链表一致
4、删除:
(1)因为是双向链表,可以自我删除该节点
(2)找到要删除的节点,假设这个节点为temp
(3)temp.pre.next=temp.next
(4)temp.next.pre=temp.pre

添加节点(按顺序):
在这里插入图片描述
步骤:
(1)找到要添加节点位置的前一个节点(temp)
(2)node.next=temp.next
(3)temp.next.pre=node
(4)temp.next=node
(5)node.pre=temp

代码实现:

public class DoubleLinkedList {
	 //创建头结点。表示链表的头
	private Node Head=new Node(0,"","");
	
	//返回头结点
	public Node getHead() {
		return Head;
	}
	//AddNode1:添加节点到单链表的尾部
	//思路:当不考虑节点顺序
	//1、找到链表的最后一个节点
	//2、将最后这个节点的Next指向新节点
	public void AddNode1(Node node) {
		//因为头节点不能动,所以需要一个辅助节点遍历
		Node temp=Head;
		while(true) {
			//找到链表的最后一个节点
			if(temp.next==null) {
				break;
			}
			//否则temp=temp的下一个节点
			temp=temp.next;
			
		}
		//循环出来之后,temp是最后一个节点
		temp.next=node;
		node.pre=temp;
	}
	
	
	//AddNode2:添加节点,按顺序
	public void AddNode2(Node node) {
		//因为头结点不能动,所以需要一个辅助节点遍历,找到添加新节点的位置
		Node temp=Head;
		boolean flag=false; //用于标识链表中是否已经存在新节点的顺序
		while(true) {
			//如果该节点是最后一个节点,则新节点添加到最后一个位置
			if(temp.next==null) {
				break;
			}else if(temp.next.number>node.number) { //说明找到了添加新节点的位置
				break;
			}else if(temp.next.number==node.number) { //说明新节点的顺序已经存在在链表中
				flag=true;
			}
			temp=temp.next;
		}
		if(flag) {
			System.out.println("该节点的顺序已经存在,插入失败");
		}else {
			//则说明新节点在链表中不存在,插入新节点
			//新节点的下一个节点=辅助节点的下一个节点
			node.next=temp.next;
			if(temp.next!=null) {   //如果temp的下一个节点不为空,则temp的下一个节点的前一个节点为新节点
				temp.next.pre=node;
			}
			//辅助节点的下一个节点=新节点
			temp.next=node;
			//新节点的前一个节点为辅助节点
			node.pre=temp;
		}
		
	}
	
	//删除节点
	public void remove(Node node) {
		if(Head.next==null) {
			System.out.println("链表为空!");
			return;
		}
		//创建辅助节点
		Node temp=Head.next;
		boolean flag=false; //标识是否找到了要删除的节点
		while(true) {
			if(temp==null) { //遍历完链表了
				break;
			}else if(temp.number==node.number) { //找到要删除的节点了
				flag=true;
				break;
			}
			temp=temp.next;
		}
		if(flag) { //链表中存在要删除的节点
			
				temp.pre.next=temp.next;	//令temp的前一个节点的下一个节点为temp的后一个节点
				if(temp.next!=null) {       //如果temp不为最后一个节点的话
					temp.next.pre=temp.pre;    //令temp的下一个节点的前一个节点为temp的前一个节点
				}
			
		}else {
			System.out.printf("不存在编号为%d的节点",node.number);
		}
	}
	
	//修改节点,按照节点的Number来修改
	public void update(Node newNode) {
		if(Head.next==null) {
			System.out.println("链表为空!");
			return;
		}
		//创建辅助节点,对链表遍历,知道找到等于修改节点的number的时候
		Node temp=Head.next;
		boolean flag=false; //用来标识是否找到了修改节点的Number
		while(true) {
			if(temp==null) { //则已经遍历完链表
				break;
			}
			if(temp.number==newNode.number) {
				flag=true;
				break;
			}
			temp=temp.next;
		}
		if(flag) {
			temp.name=newNode.name;
			temp.nickName=newNode.nickName;
		}else {
			System.out.printf("没有找到编号为%d的节点",newNode.number);
		}
	}
	//展示链表
	public void show() {
		if(Head.next==null) {
			System.out.println("链表为空!");
			return;
		}
		//因为头节点不能动,所以通过辅助节点遍历链表
		Node temp=Head.next;
		while(true) {
			//判断是不是最后一个节点
			if(temp.next==null) {
				System.out.println(temp);
				break;
			}
			System.out.println(temp);
			//temp指向下一个节点
			temp=temp.next;
		}
	}

}

//创建节点
class Node{
	public int number;
	public String name;
	public String nickName;
	public Node next; //指向下一个节点
	public Node pre;//指向前一个节点
	//构造器
	public Node(int number,String name,String nickName) {
		this.number=number;
		this.name=name;
		this.nickName=nickName;
		
		
	}

	@Override
	public String toString() {
		return "Node [number=" + number + ", name=" + name + ", nickName=" + nickName + "]";
	}
}

测试代码:

public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Node node1=new Node(1,"宋江","及时雨");
		Node node2=new Node(2,"卢俊义","玉麒麟");
		Node node3=new Node(3,"吴用","智多星");
		Node node4=new Node(4,"林冲","豹子头");
		Node node5=new Node(4,"linchong","豹子头");
		//创建一个链表
		DoubleLinkedList linkedList=new DoubleLinkedList();
		linkedList.AddNode2(node1);
		linkedList.AddNode2(node3);
		linkedList.AddNode2(node4);
		linkedList.AddNode2(node2);
		linkedList.show();
		
		System.out.println("------------");
		linkedList.remove(node4);
		linkedList.show();
	}

结果:
Node [number=1, name=宋江, nickName=及时雨]
Node [number=2, name=卢俊义, nickName=玉麒麟]
Node [number=3, name=吴用, nickName=智多星]
Node [number=4, name=林冲, nickName=豹子头]
————————————————————————
Node [number=1, name=宋江, nickName=及时雨]
Node [number=2, name=卢俊义, nickName=玉麒麟]
Node [number=3, name=吴用, nickName=智多星]

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
双向链表是一种数据结构,每个节点包含了指向前一个节点和后一个节点的指针。在 Java 中,可以使用自定义类来实现双向链表。以下是一个简单的双向链表实现示例: ```java public class DoublyLinkedList { private Node head; private Node tail; private class Node { int data; Node prev; Node next; public Node(int data) { this.data = data; this.prev = null; this.next = null; } } public void addToFront(int data) { Node newNode = new Node(data); if (head == null) { head = newNode; tail = newNode; } else { newNode.next = head; head.prev = newNode; head = newNode; } } public void addToBack(int data) { Node newNode = new Node(data); if (head == null) { head = newNode; tail = newNode; } else { tail.next = newNode; newNode.prev = tail; tail = newNode; } } public void remove(int data) { Node current = head; while (current != null) { if (current.data == data) { if (current == head) { head = current.next; if (head != null) { head.prev = null; } } else if (current == tail) { tail = current.prev; if (tail != null) { tail.next = null; } } else { current.prev.next = current.next; current.next.prev = current.prev; } break; } current = current.next; } } public void printList() { Node current = head; while (current != null) { System.out.print(current.data + " "); current = current.next; } System.out.println(); } } ``` 以上代码中的 `DoublyLinkedList` 类实现双向链表的常见操作,如在头部和尾部添加节点、删除指定节点以及打印链表。你可以创建 `DoublyLinkedList` 对象并调用相应的方法来操作双向链表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值