欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

双向链表的基本原理和实现(Java)

程序员文章站 2024-02-05 12:09:10
...

双向链表基本原理:

双向链表也是链表的一种,它每个数据结点中都有两个结点,分别指向其直接前驱和直接后继。所以我们从双向链表的任意一个结点开始都可以很方便的访问其前驱元素和后继元素。
双向链表的结构如下图所示:
双向链表的基本原理和实现(Java)

双向链表的基本操作:

分析 双向链表的遍历,添加,修改,删除的操作思路

  1. 遍历:和单链表一样,只是可以向前,也可以向后查找
  2. 添加 (默认添加到双向链表的最后):
    (1) 先找到双向链表的最后这个节点
    (2) temp.next = newHeroNode
    (3) newHeroNode.pre = temp;
  3. 修改:思路和原来的单向链表一样.
  4. 删除:
    (1) 因为是双向链表,因此,我们可以实现自我删除某个节点
    (2) 直接找到要删除的这个节点,比如temp
    (3) temp.pre.next = temp.next
    (4) temp.next.pre = temp.pre;

代码实现:

package LinkedList;

public class DoubleLinkListDemo {
	public static void main(String[] args) {
		System.out.println("双向链表的测试");
		// 先创建节点
		HeroNod hero1 = new HeroNod(1, "宋江", "及时雨");
		HeroNod hero2 = new HeroNod(2, "卢俊义", "玉麒麟");
		HeroNod hero3 = new HeroNod(3, "吴用", "智多星");
		HeroNod hero4 = new HeroNod(4, "林冲", "豹子头");
		// 创建一个双向链表
		DoubleLinkList doubleLinkList = new DoubleLinkList();
		doubleLinkList.add(hero1);
		doubleLinkList.add(hero2);
		doubleLinkList.add(hero3);
		doubleLinkList.add(hero4);
		System.out.println("修改前");
		doubleLinkList.list();

		HeroNod newHeroNode = new HeroNod(4, "公孙胜", "入云龙");
		doubleLinkList.update(newHeroNode);
		System.out.println("修改后");
		doubleLinkList.list();

		HeroNod new2HeroNode = new HeroNod(2, "卢俊义", "玉麒麟");
		doubleLinkList.delete(new2HeroNode);
		System.out.println("删除后");
		doubleLinkList.list();

	}

}

class DoubleLinkList {
	private HeroNod head = new HeroNod(0, "", "");

	// 向list中添加节点
	public HeroNod getHead() {
		return head;
	}

	// 遍历双向链表
	public void list() {
		if (head.next == null) {
			System.out.println("该链表为空,无法遍历");
			return;
		}
		HeroNod temp = head.next;
		while (true) {
			if (temp == null)
				break;
			System.out.println(temp);
			temp = temp.next;
		}
	}

	// 向双向链表中
	public void add(HeroNod heronode) {
		HeroNod temp = head;
		while (true) {
			if (temp.next == null)// 链表的辅助变量temp指向链表的最后一个元素
				break;
			temp = temp.next;
		}
		temp.next = heronode;
		heronode.pre = temp;
	}

	// 修改双向链表中指定的值
	public void update(HeroNod heronode) {
		if (head.next == null) {
			System.out.println("双向链表为空,无法修改指定元素");
			return;
		}
		HeroNod temp = head.next;
		boolean flag = false;
		while (true) {
			// 已遍历到链表的终点
			if (temp == null) {
				break;
			}
			// 找到要修改的no
			if (temp.no == heronode.no) {
				flag = true;
				break;
			}
			// 跳转到下一个节点
			temp = temp.next;
		}
		if (flag == false) {
			System.out.println("链表中不存在要修改的元素的no");
			return;
		} else {
			temp.name = heronode.name;
			temp.nickName = heronode.nickName;
		}
	}

	// 删除指定节点
	public void delete(HeroNod heronode) {
		HeroNod temp = head.next;
		boolean flag = false;
		while (true) {
			if (temp == null)
				break;
			if (temp.no == heronode.no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag == true) {
			temp.pre.next = temp.next;
			temp.next.pre = temp.pre;
		} else {
			System.out.println("链表中不存在要删除的元素的no");
			return;
		}
	}
}

class HeroNod {
	public int no;
	public String name;
	public String nickName;
	public HeroNod next;
	public HeroNod pre;

	public HeroNod(int no, String name, String nickName) {
		super();
		this.no = no;
		this.name = name;
		this.nickName = nickName;
	}
	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + ", nickName=" + nickName + "]";
	}
}

输出:

双向链表的测试
修改前
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=1, name=宋江, nickName=及时雨]
HeroNode [no=3, name=吴用, nickName=智多星]
HeroNode [no=4, name=公孙胜, nickName=入云龙]

为何要引入双向链表:

1、单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
2、单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到temp,temp是待删除节点的前一个节点。