【完整程序】Java实现单链表+双链表操作+单向循环链表

参考自视频:《尚硅谷Java数据结构和Java算法》,并对代码进行详细解释

一、单链表

在这里插入图片描述

public class SingleLinkedListDemo {

	public static void main(String[] args) {
		//创建结点对象
		HeroNode hero1 = new HeroNode(1,"宋江","及时雨");
		HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");
		HeroNode hero3 = new HeroNode(3,"吴用","智多星");
		HeroNode hero4 = new HeroNode(4,"林冲","豹子头");

		//创建链表对象
		SingleLinkedList single = new SingleLinkedList();

		//加入结点
		single.add(hero1);
		single.add(hero2);
		single.add(hero3);
		single.add(hero4);

		//显示链表
		single.list();
	}
}

//2.创建一个类来管理链表
class SingleLinkedList{
	//先初始化一个头结点,设为私有,无法被其他类调用,不存放数据
	private HeroNode head = new HeroNode(0,"","");
	//2.1添加结点的方法
	public void add(HeroNode heronode){
		//由于head不能动,所以需要一个辅助结点temp来遍历
		HeroNode temp = head;
		//遍历链表,找到最后一个结点 !
		while(true) {
			if(temp.next==null) {
				break;//说明已经指向了链表的最后null,所以跳出循环直接指向插入操作
			}
			temp = temp.next;//没有到最后一个结点,temp结点后移
		}
		temp.next = heronode;//让最后一个结点的next域指向新结点
	}
	
	//2.2显示链表
	public void list() {
		//先判断链表是否为空,为空即头结点指向的第一个节点为空结点
		if(head.next==null) {
			System.out.println("结点为空");
			return;//结束方法
		}
		HeroNode temp = head;//head不能动,用辅助结点来遍历
		//通过遍历整个链表来输出结点对象
		while(true) {
			if(temp.next == null) {
				break;//跳出循环
			}
			temp = temp.next;//temp后移
			//输出结点信息
			System.out.println(temp);//输出辅助结点对象,之前写过了toString方法
		}
	}
}

//1.写一个结点类,由内容和指针组成,在类中若以以下结构定义,会直接默认结点类
class HeroNode{
    //内容data
	public int no;
	public String name;
	public String nickname;
	//next是HeroNode结点对象的对象(属性)
	public HeroNode next;//next是指向下一个结点的指针对象,存放下一结点地址域
	
	//构造器,用于构造对象,将对象的实例变量初始化,即将类中成员变量传给对象
	public HeroNode(int no,String name,String nickname) {
		this.no=no;//this对象的成员变量等于传进来的类中的成员变量
		this.name=name;
		this.nickname=nickname;
	}
	//为输出想要的对象格式,重写toString方法
	@Override
	public String toString() {
		return "HeroNode[no="+no+",name="+name+",nickname="+nickname+"]";
	}
}

在这里插入图片描述

二、双向链表

在这里插入图片描述
——每个结点都带有两个指针的

添加数据

temp.next = new Node(data);
Node.pre = temp;

删除数据

1.可以实现自我删除temp;
2. temp.pre.next=temp.next; //temp的前一个结点指向了temp的后一个结点
3.temp.next.pre = temp.pre//因为是双向的,所以还需要temp的后一个结点指向temp的前一个结点

【双链表的操作】:

package queue;

public class DoubleLinkedListDemo {

	public static void main(String[] args) {
		Node node1 = new Node(10);
		Node node2 = new Node(20);
		Node node3 = new Node(30);
		Node node4 = new Node(40);
		Node node5 = new Node(50);
		
		DoubleLinkedList dl = new DoubleLinkedList();
		dl.add(node1);
		dl.add(node2);
		dl.add(node3);
		dl.add(node4);
		dl.add(node5);
		dl.list();
		System.out.println("删除结点后:");
		dl.delectNode(30);
		dl.list();
	}
}

//2.管理结点的链表类
class DoubleLinkedList{
	private Node head = new Node(0);
	
	//添加结点
	public void add(Node node) {
		Node temp = head;
		//找出末端的结点
		while(true) {
			if(temp.next==null) {
				break;
			}
			temp = temp.next;
		}
		//添加结点,形成双向链表
		temp.next = node;//让最后一个结点指向新结点
		node.pre = temp;//双向连接
	}
	
	
	//删除结点
	public void delectNode(int data) {
		if(head.next==null) {
			System.out.println("链表为空!");
			return;//结束方法
		}
		Node temp = head;//如果是单链表,需要找到待删除结点的前一个,这里找到其本身即可
		boolean flag = false;
		while(true) {
			if(temp == null) {
				break;//已到链表末端
			}
			if(temp.data == data) {
				flag=true;
				break;
			}
			temp = temp.next;
		}
		if(flag) {//已经找到该结点
			temp.pre.next=temp.next;//这句也可以用于删除最后一个结点
			//如果是最后一个结点就不需要执行下一句
			if(temp.next!=null) {
				temp.next.pre=temp.pre;
			}
		}
	}
	
	//显示链表
	public void list() {
		if(head.next==null) {
			System.out.println("结点为空!");
			return;
		}
		Node temp = head;
		while(true) {
			if(temp.next==null) {
				break;
			}
			temp=temp.next;
			System.out.println(temp);
		}
	}
}

//1.双链表的结点类
class Node{
	public int data;
	public Node next;
	public Node pre;
	
	//构造器
	public Node(int data) {
		this.data = data;
	}
	
	@Override
	public String toString() {
		return "Node=["+data+"]";
	}
}

在这里插入图片描述

三、单向循环链表

问题的引出——约瑟夫问题(Josephu)

问题描述:编号为1-n的小孩围成一圈,约定编号为k的人从1开始报数,数到m的那个人出列,他的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人都出列,由此产生一个出队编号的序列。

思路

可用一个不带头结点的循环链表来处理:先构成一个有n个节点的循环单链表,然后由k结点起从1开始计数,计到m时,对于的结点从链表中删除,然后从被删除结点的下一个结点又从1开始计数,知道最后一个结点被删除。

【手撕链表操作】

public class Main{
    public static void main(String[] args){
        Node node0 = new Node(0);
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);
		Node node5 = new Node(5);

		Node head = new Node(0);

		node0.next=node1;
		node1.next=node2;
		node2.next=node3;
		node3.next=node4;
		node4.next=node5;

		list(node0);
		delect(head,node0);
		list(node0);
    } 


/*
	public void add(Node node){
	    Node temp = head;
		while(true){
		    if(temp.next==null){
			    break;
			}
			temp=temp.next;
		}
		temp.next = node;
	}
*/
	public static void delect(Node head,Node delNode)//头结点,删除的结点
	{
		if(head==null || delNode==null)
		{
			return;
		}
		Node temp = head;
		if(delNode.next != null)//要删除的结点不是尾结点
		{
			delNode.value=delNode.next.value;//将要删除的结点值替换成下一个结点的值
			delNode.next = delNode.next.next;//将要删除的结点的指针替换成下个结点指针,因为要替换它的是下个结点
		}
		else if(delNode.next==null)//如果要删除的结点是尾结点
		{
			while(temp.next!=delNode)//用临时指针从头结点开始遍历,到达尾结点前一个结点,将指向null
			{
				temp = temp.next;
			}
			temp.next=null;
		}
	}

	public static void list(Node node)
	{
		while(node != null)
		{
			System.out.println(node.value);
			node = node.next;
		}
	}
}

class Node
{
	int value;
	Node next;
	public Node(int value){
		this.value = value;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值