第二篇 链表

本文介绍了单链表和双向链表的数据结构,包括节点定义、链表建立、增删改查操作。通过实例展示了如何按编号顺序插入节点、删除指定节点、修改节点信息以及查找倒数第K个节点。此外,还讨论了单链表的逆置方法,如栈实现和头插法,并展示了两个有序单链表的合并。最后,探讨了约瑟夫问题的循环链表实现。
摘要由CSDN通过智能技术生成

单链表

定义节点

class HeroNode {
	public int no;
	public String name;
	public String nickname;
	public HeroNode next;
	public HeroNode(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 +
                '}';
    }
}

建立单链表

class SingleLinkedList {
	//头节点
	private HeroNode head = new HeroNode(0, "", "");
	public HeroNode getHead() {
		return head;
	}
	public void setHead(HeroNode head) {
		this.head = head.next;
	}
	//添加节点
	public void add(HeroNode heroNode) {
		HeroNode temp = head;
		while (true) {
			if (temp.next == null) {
				break;
			}
			temp = temp.next;
		}
		temp.next = heroNode;
	}
	//按编号顺序添加节点
	public void addByOrder(HeroNode heroNode) {
		HeroNode temp = head;
		boolean flag = false;
		while (true) {
			if (temp.next == null) {
				break;
			}
			if (temp.next.no > heroNode.no) {
				break;
			} else if (temp.next.no == heroNode.no) {	
				flag = true;
				break;			
			}
			temp = temp.next;
		}
		if (flag) {
			System.out.println("编号已存在 不能插入");
		} else {
			heroNode,next = temp.next;
			temp.next = heroNode;	
		}
	}
	//更新节点
	public void update(HeroNode newHeroNode) {
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		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.println("没找到 不能修改");
		}
	}
	//打印链表
	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.next;
		}
	}
	public void del(int no) {
		HeroNode temp = head;
		boolean flag = false;
		while (true) {
			if (temp.next == null) {
				break;
			}
			if (temp.next.no == no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.next = temp.next.next;
		} else {
			System.out.println("要删除的节点不存在");
		}
	}
}

测试代码 建立单链表(按照节点输入顺序)

public class SingleLinkedListDemo {
	public static void main(String[] args) {
		HeroNode hero1 = new HeroNode(1, "aaa", "aaa1");
		HeroNode hero2 = new HeroNode(3, "bbb", "bbb1");
		HeroNode hero3 = new HeroNode(5, "ccc", "ccc1");
		HeroNode hero4 = new HeroNode(7, "ddd", "ddd1");
	}
	SingleLinkedList singleLinkedList1 = new SingleLinkedList();
	singleLinkedList1.add(hero1);
	singleLinkedList1.add(hero2);
	singleLinkedList1.add(hero3);
	singleLinkedList1.add(hero4);
	singleLinkedList1.list();
	
}

在这里插入图片描述

测试代码 建立单链表(按照节点编号顺序)

		HeroNode hero1 = new HeroNode(1, "aaa", "aaa1");
        HeroNode hero2 = new HeroNode(7, "bbb", "bbb1");
        HeroNode hero3 = new HeroNode(5, "ccc", "ccc1");
        HeroNode hero4 = new HeroNode(3, "ddd", "ddd1");
        SingleLinkedList singleLinkedList1 = new SingleLinkedList();

        singleLinkedList1.addByOrder(hero1);
        singleLinkedList1.addByOrder(hero2);
        singleLinkedList1.addByOrder(hero3);
        singleLinkedList1.addByOrder(hero4);
        singleLinkedList1.list();

在这里插入图片描述

删除节点

		System.out.println("删除3号节点:");
        singleLinkedList1.del(3);
        singleLinkedList1.list();

在这里插入图片描述

修改节点

		System.out.println("修改5号节点");
        HeroNode newHeroNode = new HeroNode(5, "eee", "eee1");
        singleLinkedList1.update(newHeroNode);
        singleLinkedList1.list();

在这里插入图片描述

获取链表长度

public static int getLength(HeroNode head) {
	if (head.next == null) {
		return 0;
	}
	int length = 0;
	HeroNode cur = head.next;
	while (cur != null) {
		length++;
		cur = cur.next;
	}
	return length;
}

测试代码:

System.out.println("链表长度为: " + getLength(singleLinkedList1.getHead()));

在这里插入图片描述

查找倒数第K个节点

public static HeroNode findLastIndexNode(HeroNode head, int index) {
	if (head.next == null) {
		return null;
	}
	int size = getLength(head);
	if (index <= 0 || index > size) {
		return null;
	}
	HeroNode cur = head.next;
	for (int i = 0; i < size - index; i++) {
		cur = cur.next;
	}
	return cur;
}

测试代码:

		System.out.println("查看倒数第1个节点");
        HeroNode res = findLastIndexNode(singleLinkedList1.getHead(), 1);
        System.out.println(res);

在这里插入图片描述

单链表逆置

利用栈实现链表逆置

public static void reversePrint(HeroNode head) {
	if (head.next == null) {
		return;
	}
	Stack<HeroNode> stack = new Stack<~>();
	HeroNode cur = head.next;
	while (cur != null) {
		stack.push(cur);
		cur = cur.next;
	}
	while (stack.size() > 0) {
		System.out.println(stack.pop());
	}
}

测试代码:

		singleLinkedList1.list();
        System.out.println("逆置后:");
        reversePrint(singleLinkedList1.getHead());

在这里插入图片描述

头插法实现链表逆置

public static void reverseList(HeroNode head) {
	if (head.next == null || head.next.next == null) {
		return;
	}
	HeroNode cur = head.next;
	HeroNode next = null;
	HeroNode reverseHead = new HeroNode(0, "", "");
	while (cur != null) {
		next = cur.next;
		cur.next = reverseHead.next;
		reverseHead.next = cur;
		cur = next;
	}
	head.next = reverseHead.next;
}

测试代码:

		System.out.println("逆置后:");
        reverseList(singleLinkedList1.getHead());
        singleLinkedList1.list();

在这里插入图片描述

单链表合并(两个有序单链表 合并之后依然有序)

public static HeroNode SingleLinkedListMerge(HeroNode list1, HeroNode list2) {
	HeroNode temp = new HeroNode(0, "", "");
	HeroNode head = temp;
	while (list1 != null && list2 != null) {
		if (list1.no < list2.no) {
			temp.next = list1;
			list1 = list1.next;
		} else {
			temp.next = list2;
			list2 = list2.next;
		}
		temp = temp.next;
	}
	if (list1 == null) {
		temp.next = list2;
	}
	if (list2 == null) {
		temp.next = list1;
	}
	return head.next;
}

测试代码:

HeroNode hero1 = new HeroNode(1, "aaa", "aaa1");
        HeroNode hero2 = new HeroNode(3, "bbb", "bbb1");
        HeroNode hero3 = new HeroNode(5, "ccc", "ccc1");
        HeroNode hero4 = new HeroNode(7, "ddd", "ddd1");
        HeroNode hero5 = new HeroNode(2, "aaa", "aaa2");
        HeroNode hero6 = new HeroNode(4, "bbb", "bbb2");
        HeroNode hero7 = new HeroNode(6, "ccc", "ccc2");
        HeroNode hero8 = new HeroNode(8, "ddd", "ddd2");

        SingleLinkedList singleLinkedList1 = new SingleLinkedList();

        singleLinkedList1.add(hero1);
        singleLinkedList1.add(hero2);
        singleLinkedList1.add(hero3);
        singleLinkedList1.add(hero4);
        System.out.println("单链表:");
        singleLinkedList1.list();

        SingleLinkedList singleLinkedList2 = new SingleLinkedList();

        singleLinkedList2.add(hero5);
        singleLinkedList2.add(hero6);
        singleLinkedList2.add(hero7);
        singleLinkedList2.add(hero8);
        System.out.println("单链表:");
        singleLinkedList2.list();

        System.out.println("合并后:");
        SingleLinkedList singleLinkedList3 = new SingleLinkedList();
        HeroNode newHead = SingleLinkedListMerge(singleLinkedList1.getHead(), singleLinkedList2.getHead());
        singleLinkedList3.setHead(newHead);
        singleLinkedList3.list();

在这里插入图片描述

双链表

定义节点

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 "HeroNode2{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}

建立双向链表

class DoubleLinkedList {
	private HeroNode2 head = new HeroNode2(0, "", "");
	public HeroNode2 getHead() {
		return head;
	}
	public void list() {
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		HeroNode2 temp = head.next;
		while (true) {
			if (temp == null) {
				break;
			}
			System.out.println(temp);
			temp = temp.next;
		}
	}
	public void addByOrder(HeroNode2 heroNode) {
		HeroNode2 temp = head;
		boolean flag = false;
		while (true) {
			if (temp.next == null) {
				break;
			}
			if (temp.next.no > heroNode.no) {
				break;
			} else if (temp.next.no == heroNode.no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			System.out.println("编号已存在 不能插入");
		} else {
			if (temp.next == null) {
				temp.next = heroNode;
				heroNode.pre = temp;
			} else {
				heroNode,next = temp.next;
				temp.next.pre = heroNode;
				heroNode.pre = temp;
				temp.next = heroNode;
			}
		}
	}
	//添加一个节点到双向链表的最后
	public void add(HeroNode2 heroNode) {
		HeroNode2 temp = head;
		while(true) {
			if (temp.next == null) {
				break;
			}
			temp = temp.next;
		}
		temp.next = heroNode;
		heroNode.pre = temp;
	}
	public void update(HeroNode2 newHeroNode) {
		if (head.next == null) {
			System.out.println("链表为空");
			return;	
		}
		HeroNode2 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.println("没找到");
		}
	}
	public void del(int no) {
		if (head.next == null) {
			System.out.println("链表为空");
			return;
		}
		HeroNode2 temp = head.next;
		boolean flag = false;
		while (true) {
			if (temp == null) {
				break;
			}
			if (temp.no == no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.pre.next = temp.next;
			if (temp.next != null) {
				temp.next.pre = temp.pre;
			}
		} else {
			System.out.println("要删除的节点不存在");
		}
	}
}

测试

建立双向链表(按节点加入顺序)
public class DoubleLinkedListDemo {
	public static void main(String[] args) {
		HeroNode2 hero1 = new HeroNode2(1, "a", "a1");
		HeroNode2 hero2 = new HeroNode2(4, "b", "b1");
        HeroNode2 hero3 = new HeroNode2(3, "c", "c1");
        HeroNode2 hero4 = new HeroNode2(5, "e", "e1");
        HeroNode2 hero5 = new HeroNode2(2, "d", "d1");
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        doubleLinkedList.add(hero1);
        doubleLinkedList.add(hero2);
        doubleLinkedList.add(hero3);
        doubleLinkedList.add(hero4);
        doubleLinkedList.add(hero5);
        doubleLinkedList.list();
	}
}

在这里插入图片描述

建立双向链表(按节点编号顺序)
		HeroNode2 hero1 = new HeroNode2(1, "a", "a1");
        HeroNode2 hero2 = new HeroNode2(4, "b", "b1");
        HeroNode2 hero3 = new HeroNode2(3, "c", "c1");
        HeroNode2 hero4 = new HeroNode2(5, "e", "e1");
        HeroNode2 hero5 = new HeroNode2(2, "d", "d1");


        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        doubleLinkedList.addByOrder(hero1);
        doubleLinkedList.addByOrder(hero2);
        doubleLinkedList.addByOrder(hero3);
        doubleLinkedList.addByOrder(hero4);
        doubleLinkedList.addByOrder(hero5);
        doubleLinkedList.list();

在这里插入图片描述

修改节点
		HeroNode2 newHeroNode = new HeroNode2(4, "e", "e1");
        doubleLinkedList.update(newHeroNode);
        System.out.println("修改后");
        doubleLinkedList.list();

在这里插入图片描述

删除节点
		doubleLinkedList.del(3);
        System.out.println("删除后:");
        doubleLinkedList.list();

在这里插入图片描述

约瑟夫问题(循环链表)

场景

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实现

定义节点

class Boy {
	private int no;
	private Boy next;
	public Boy(int no) {
		this.no = no;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public Boy getNext() {
		return next;
	}
	public void setNext(Boy next) {
		this.next = next;
	}
}

循环链表

class CircleSingleLinkedList {
	private Boy first = null;
	public void addBoy(int nums) {
		if (nums < 1) {
			System.out.println("nums的值不正确");
			return;
		}
		Boy curBoy = null;
		for (int i = 1; i <= nums; i++) {
		Boy boy = new Boy(i);
		if (i == 1) {
			first = boy;
			first.setNext(first);
			curBoy = first;
		} else {
			curBoy.setNext(boy);
			boy.setNext(first);
			curBoy = boy;
		}
	}
	}
	public void showBoy() {
		if (first == null) {
			System.out.println("没有任何小孩");
			return;
		}
		Boy curBoy = first;
		while (true) {
			System.out.printf("小孩的编号 %d\n", curBoy.getNo());
			if (curBoy.getNext() == first) {
				break;
			}
		curBoy = curBoy.getNext();
		}
	}
	public void countBoy(int startNo, int countNum, int nums) {
		if (first == null || startNo < 1 || startNo > nums) {
			System.out.println("参数有误");
			return;
	}
	Boy helper = first;
	while (true) {
		if (helper.getNext() == first) {
				break;
		}
		helper = helper.getNext();
	}
	for (int j = 0; j < startNo - 1; j++) {
		first = first.getNext();
		helper = helper.getNext();
	}
	while (true) {
		if (helper == first) {
			break;
		}
		for (int j = 0; j < countNum - 1; j++) {
			first = first.getNext();
			helper = helper.getNext();
		}
		System.out.printf("小孩%d出圈\n", first.getNo());
		first = first.getNext();
		helper.setNext(first);
	}
		System.out.printf("最后留在圈中的小孩编号%d\n", first.getNo());
	}
}

测试

public class Josefu {
	public static void main(String[] args) {
		CircleSingLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
		circleSingleLinkedList.addBoy(5);
		circleSingleLinkedList.showBoy();
		circleSingleLinkedList.countBoy(1, 2, 5);
	}
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值