数据结构与算法day07-双向链表应用案例

使用带head头的双向链表实现-水浒传排行榜管理

单链表的缺点:

1.单链表,查找的方向只能是一个方向,而双向链表可以
向前或向后查找
2.单链表不能自我删除,需要靠辅助节点(指针),而双向
链表,则不用辅助指针,所以前面我们单链表删节点,
总是找到temp,temp是待删除节点的前一个接点
3.示意图帮助理解删除

在这里插入图片描述

双向链表代码如下:

// 定义DoubleLinkedList 管理英雄
class DoubleLinkedList {
	// 先初始化头结点,头结点不要动(改变头结点将无法找到后续节点)
	private HeroNode head = new HeroNode(0, "", "");
	
	public HeroNode getHead() {
		return head;
	}

	public void setHead(HeroNode head) {
		this.head = head;
	}

	// 和单链表方法几乎一样
	public void add(HeroNode heroNode) {
		// 因为head节点不能动,因此我们需要一个辅助变量temp
		HeroNode temp = head;
		// 遍历链表,找到最后
		while (true) {
			// 找到链表的最后
			if (temp.next == null) {
				break;
			}
			// 如果没有找到最后,将temp后移
			temp = temp.next;
		}
		// 当退出while循环时,temp就指向了链表的最后
		// 形成一个双向链表
		temp.next = heroNode;
		heroNode.pre = temp;
	}
	
	
	
	
	// 方法和单链表一样
	// 修改节点的信息,根据no编号来修改,即no编号不能改
	// 说明
	// 1.根据newHeroNode的no来修改即可
	public void update (HeroNode newHeroNode) {
		// 判断是否空
		if (head.next == null) {
			System.out.println("链表为空~");
			return;
		}
		// 找到需要修改的节点,根据no编号来找
		// 定义一个辅助变量
		HeroNode temp = head.next;
		boolean flag = false; // 是否找到了该节点
		while (true) {
			if (temp == null) {
				break; // 已经遍历完链表
			}
			if (temp.no == newHeroNode.no) {
				// 找到了
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.name = newHeroNode.name;
			temp.nickname = newHeroNode.nickname;
		} else { // 没有找到需要修改的节点
			System.out.printf("没有找到编号%d的节点\n", newHeroNode.no);
		}
	}
	
	// 删除双向链表节点的代码
	public void del(int no) {
		// 为什么要这么做,因为删除双向链表不需要找到
		// 待删除节点的前一个节点temp
		// 只需要找到需要删除的节点,自己删除即可
		
		// 判断当前链表是否为空
		if (head.next == null) {
			System.out.println("链表为空,无法删除~");
			return;
		}
		// 辅助指针
		HeroNode cur = head.next;
		boolean flag = false; // 标识是否找到待删除的节点
		while (true) {
			if (cur == null) {// 已经到链表最后节点的next
				break;
			}
			if (cur.no == no) {
				// 找到了待删除节点cur
				flag = true;
				break;
			}
			cur = cur.next; // temp后移,遍历
		}
		// 判断flag
		if (flag) {// 找到了
			cur.pre.next = cur.next;
			// 如果是最后一个节点,就不需要执行下面,否则会出现空指针异常
			if (cur.next != null) {
				cur.next.pre = cur.pre;
			}
			
		} else {
			System.out.printf("要删除的节点%d不存在~\n", no);
		}
	}
	
	// 显示链表【遍历】
	// 方法和单链表一样
	public void list() {
		// 判断链表是否为空
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		// 因为头节点不能动,因此需要辅助变量来遍历
		HeroNode temp = head.next;
		while (true) {
			// 判断是否到链表最后
			if (temp == null) {
				break;
			}
			// 输出节点信息
			System.out.println(temp);
			// 将temp后移,一定小心,不后移会造成死循环
			temp = temp.next;
		}
	}
}

// 定义HeroNode,每个HeroNode对象就是一个节点
class HeroNode {
	public int no;
	public String name;
	public String nickname;
	// 指向下一个节点,默认是null
	public HeroNode next;
	// 指向上一个节点,默认是null
	public HeroNode pre;
	
	// 构造器
	public HeroNode(int no, String name, String nickname) {
		this.no = no;
		this.name = name;
		this.nickname = nickname;
	}

	// 为了显示方便,重写toString
	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
	}
}

	public void addByOrder(HeroNode heroNode) {
		// 按照单链表的顺序添加思路
		
		//  空链表
		if (head.next == null) {
			heroNode.pre = head;
			head.next = heroNode;
			return;
		}
		HeroNode temp = head;
		HeroNode next = null;
		while (true) {
			if (temp.next == null) {// 遍历到双链表尾部
				temp.next = heroNode;
				heroNode.pre = temp;
				break;
			}
			if (temp.next.no > heroNode.no) {// 找到要插入的位置
				next = temp.next;
				temp.next = heroNode;
				heroNode.pre = temp;
				if (next != null) {
					heroNode.next = next;
					next.pre = heroNode;
				}
				break;
			}
			if (temp.next.no == heroNode.no) {// 找到相同的节点
				System.out.printf("要插入的no=%d已经存在\n", heroNode.no);
				break;
			}
			temp = temp.next;
		
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值