Java数据结构之双向链表

什么是双向链表

  • 结构类似于单向链表,但是每个节点多了一个pre用于指向前一个结点,这样的特性使得双向链表可以向前或者向后查找节点,而单链表的查找只能有向一个方向查找。
  • 单链表笔记
  • 其逻辑结构如下图
  • 在这里插入图片描述

双向链表增删改查

添加节点

  • 添加节点的操作和单链表差不多,但是除了链表最后一个节点的next指向新节点外,增加了一个新节点的pre指向前一个结点的操作。
  • 代码如下
// 直接插入到链表尾部
		public void add(Node2 node) {
			Node2 temp = Head;
			while (true) {// 查找单链表尾部,如果为null说明到达尾部,跳出循环
				if (temp.getNext() == null) {
					break;
				}
				temp = temp.getNext();// 否则令temp指向下一个节点
			}
			temp.setNext(node);
			node.setPre(temp);
			// 找到尾部后,向尾部插入节点
		}

遍历链表

  • 从头节点开始向后遍历的代码和单链表的一样
  • 代码如下
public void show() {// 头的数据不能展示,展示的是头之后的节点的数据
		Node2 temp = Head.getNext();// 将头之后的第一个节点赋值给辅助变量
		while (true) {
			if (temp == null) {// 如果该节点为null说明到尾部了
				break;
			}
			System.out.println(temp.toString());
			// 不为null,说明有数据,输出该节点的数据
			temp = temp.getNext();
			// 令辅助变量指向下一个节点
		}
	}

修改结点数据

  • 从头节点开始向后遍历的代码和单链表基本一样
  • 代码如下
public void update(Node2 node) {
			Node2 temp = Head.getNext();
			boolean flag = false;
			while (true) {
				if (temp == null) {// 链表为null或者没找到,跳出循环
					break;
				}
				if (temp.getNo() == node.getNo()) {// 找到了,跳出循环
					flag = true;
					break;
				}
				// 没找到继续往后遍历
				temp = temp.getNext();
			}
			if (flag) {
				temp.setData(node.getData());
			} else {
				if (temp == Head.getNext()) {
					System.out.println("链表为空");
				} else {
					System.out.printf("未在链表中找到no=%d的节点\n", node.getNo());
				}
			}
		}

删除节点

  • 相比单链表,因为多了一个pre用于指向前一个结点,所以双链表不需要找到需要删除的节点的前一个结点,而是直接可以让需要删除的节点自我删除。
  • 代码如下
public void delete(Node2 node) {//双向链表的删除不依靠前一个节点,可以进行自我删除
			Node2 temp = Head.getNext();
			boolean flag = false;
			while (true) {
				if (temp== null) {// 链表为null或者没找到,跳出循环
					break;
				}
				if (temp.getNo() == node.getNo()) {
					flag = true;
					break;
				}
				temp = temp.getNext();
			}
			if (flag) {
				temp.getPre().setNext(temp.getNext());//让目标节点的前一个节点的next指向目标节点的后一个节点
				if(temp.getNext()!=null) {//判断目标节点是不是最后一个节点
					temp.getNext().setPre(temp.getPre());//不是则让目标节点的后一个节点的pre指向目标节点的前一个结点	
				}
				temp.setPre(null);//让目标节点的pre指向null,彻底和链分离
				
			} else {
				if (temp == Head) {
					System.out.println("链表为空");
				} else {
					System.out.printf("链表中不存在为%d的节点\n", node.getNo());
				}
			}
		}

完整代码

  • Node2
public class Node2 {
	private Node2 pre;
	private int no;
	private String data;
	private Node2 next;

	public Node2(int no, String data) {
		this.no = no;
		this.data = data;
	}

	public Node2 getPre() {
		return pre;
	}

	public void setPre(Node2 pre) {
		this.pre = pre;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getData() {
		return data;
	}

	public void setData(String data) {
		this.data = data;
	}

	public Node2 getNext() {
		return next;
	}

	public void setNext(Node2 next) {
		this.next = next;
	}

	public String toString() {
		return "no:" + no + " data:" + data;
	}

}
  • DoubleLinkedList
public class DoubleLinkedList {
	
	private Node2 Head=new Node2(0, "");
	
	public void show() {// 头的数据不能展示,展示的是头之后的节点的数据
		Node2 temp = Head.getNext();// 将头之后的第一个节点赋值给辅助变量
		while (true) {
			if (temp == null) {// 如果该节点为null说明到尾部了
				break;
			}
			System.out.println(temp.toString());
			// 不为null,说明有数据,输出该节点的数据
			temp = temp.getNext();
			// 令辅助变量指向下一个节点
		}
	}
	
	// 直接插入数据
		public void add(Node2 node) {
			Node2 temp = Head;
			while (true) {// 查找单链表尾部,如果为null说明到达尾部,跳出循环
				if (temp.getNext() == null) {
					break;
				}
				temp = temp.getNext();// 否则令temp指向下一个节点
			}
			temp.setNext(node);
			node.setPre(temp);
			// 找到尾部后,向尾部插入节点
		}
		
		// 通过no修改节点
		public void update(Node2 node) {
			Node2 temp = Head.getNext();
			boolean flag = false;
			while (true) {
				if (temp == null) {// 链表为null或者没找到,跳出循环
					break;
				}
				if (temp.getNo() == node.getNo()) {// 找到了,跳出循环
					flag = true;
					break;
				}
				// 没找到继续往后遍历
				temp = temp.getNext();
			}
			if (flag) {
				temp.setData(node.getData());
			} else {
				if (temp == Head.getNext()) {
					System.out.println("链表为空");
				} else {
					System.out.printf("未在链表中找到no=%d的节点\n", node.getNo());
				}
			}
		}
		public void delete(Node2 node) {//双向链表的删除不依靠前一个节点,可以进行自我删除
			Node2 temp = Head.getNext();
			boolean flag = false;
			while (true) {
				if (temp== null) {// 链表为null或者没找到,跳出循环
					break;
				}
				if (temp.getNo() == node.getNo()) {
					flag = true;
					break;
				}
				temp = temp.getNext();
			}
			if (flag) {
				temp.getPre().setNext(temp.getNext());//让目标节点的前一个节点的next指向目标节点的后一个节点
				if(temp.getNext()!=null) {//判断目标节点是不是最后一个节点
					temp.getNext().setPre(temp.getPre());//不是则让目标节点的后一个节点的pre指向目标节点的前一个结点	
				}
				temp.setPre(null);//让目标节点的pre指向null,彻底和链分离
				
			} else {
				if (temp == Head) {
					System.out.println("链表为空");
				} else {
					System.out.printf("链表中不存在为%d的节点\n", node.getNo());
				}
			}
		}
		
		public static void main(String[] args) {
			DoubleLinkedList dll=new DoubleLinkedList();
			Node2 n1=new Node2(1, "1号");
			Node2 n2=new Node2(2, "2号");
			Node2 n3=new Node2(3, "3号");
			
			dll.add(n1);
			dll.add(n3);
			dll.add(n2);
			
			dll.show();
			n3.setData("三号");
			dll.update(n3);
			System.out.println("修改后");
			dll.show();
			dll.delete(n2);
			System.out.println("删除n2后");
			dll.show();
		}

}
  • 运行结果
no:1 data:1号
no:3 data:3号
no:2 data:2号
修改后
no:1 data:1号
no:3 data:三号
no:2 data:2号
删除n2后
no:1 data:1号
no:3 data:三号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值