IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 简洁笔记-Java数据结构基础(4.线性结构链表) -> 正文阅读

[数据结构与算法]简洁笔记-Java数据结构基础(4.线性结构链表)

什么是链表

非连续、非顺序的存储结构(链式存储)

1.单链表

单链表可以看作是火车一样拼接。链表存储数据的同时也要存储下一个节点在什么位置

(1).单链表基本知识和使用

//一个节点
public class Node {
//	节点内容
	int data;
//	下一个节点
	Node next;
	
	public Node(int data) {
		this.data = data;
	}
	
/*	版本1:为节点追加节点,向后找,一直找到它没有下一个节点此时再添加新的节点
	public void append(Node node) {
		this.next = node;
	}
*/
	
	
/*	版本2(循环currentNode和nextNode的不断向后跳动):为节点追加节点,向后找,一直找到它没有下一个节点此时再添加新的节点
	public void append(Node node) {
		当前节点currentNode
		Node currentNode = this;
		循环向后找
		while(true) {
			当前节点的下一个节点nextNode
			Node nextNode = currentNode.next;		
			如果没有下一个节点,即下一个节点为null,此时的currentNode节点为最后一个节点
			if(nextNode == null) {
				break;
			}			
			再把下一个节点赋给当前节点
			currentNode = nextNode;		
		}
		把需要追加的节点追加为currentNode的nextNode
		currentNode.next = node;
	}
*/
	
//		版本3(把节点对象自己返回去,可以无限向后追加,链式编程):为节点追加节点,向后找,一直找到它没有下一个节点此时再添加新的节点
	public Node append(Node node) {
		//当前节点currentNode
		Node currentNode = this;
		//循环向后找
		while(true) {
			//当前节点的下一个节点nextNode
			Node nextNode = currentNode.next;		
			//如果没有下一个节点,即下一个节点为null,此时的currentNode节点为最后一个节点
			if(nextNode == null) {
				break;
			}			
			//再把下一个节点赋给当前节点
			currentNode = nextNode;		
		}
		//把需要追加的节点追加为currentNode的nextNode
		currentNode.next = node;
		return this;
	}

	
//	获取下一个节点
	public Node next() {
		return this.next;
	}
	
//	获得这个结点的内容
	public int getData() {
		return this.data;
	}
	
//	判断当前节点是否为最后一个节点
	public boolean isLast() {
		return this.next() == null;
	}
	
	
}

编写测试类Test对单链表进行测试

public class Test {
	public static void main(String[] args) {
//		创建一些节点
		Node n1 = new Node(11);
		Node n2 = new Node(22);
		Node n3 = new Node(33);
//		追加节点
		n1.append(n2);
		n2.append(n3);
//		输出n1下一个节点
		System.out.println(n1.next().getData());	//输出结果:22
//		输出n1下下个节点
		System.out.println(n1.next().next().getData());	//输出结果:33
		Node n4 = new Node(44);
		n1.append(n4);	//此时的n4其实是追加到了n3的后面
		System.out.println(n3.next().getData());//输出结果:44
		Node n5 = new Node(55);
		Node n6 = new Node(66);
		//版本3的优势可以链式编程
		n1.append(n5).append(n6);
		System.out.println(n5.next().getData());//输出结果:66
//		测试isLast()方法判断是否为最后一个节点
		System.out.println(n5.isLast());//输出结果:false
		System.out.println(n6.isLast());//输出结果:true
		
	}	
}

(2)删除单链表的节点

删除不了当下节点,只能删除下一个节点
那怎么删除下一个节点呢?
只能通过将下下个节点赋给当下节点的下一个节点,这样的话就达到删除了下一个节点的效果

//删除单链表方法
	public void remove() {
		//当前节点currentNode
		Node currentNode = this;
		//真正删除后currentNode的下一个节点nextNode
		Node nextNode = currentNode.next.next;
		//nextNode赋值给currentNode的下一个节点,达到删除效果
		currentNode.next = nextNode;
	}

补上输出链表节点数据的show()方法

//打印输出链表元素思路:循环currentNode跳动来输出currentNode.getData()的值
	public void show() {
		Node currentNode = this;
		while(true) {
			//判定条件:如果currentNode为空则跳出循环
			if(currentNode == null) {
				break;
			}
			System.out.print(currentNode.getData()+" ");
			//实现跳动的关键地方把currentNode.next()赋值给currentNode实现不断向后跳动
			currentNode = currentNode.next();
		}
		System.out.println();
	}

进行删除n3的下一个节点的操作

代码?????????????????输出结果

?(3)往单链表插入节点

/*单链表指定位置插入节点思路:	比如已有n1,n2,n3,把新节点n4插入到n2的后面
 * 需要弄一个tempNode 取得 n3的值
 * Node tempNode = n2.next();
 * n2.next = n4;
 * n4.next = tempNode;
*/
	public void insert(Node node) {
		Node tempNode;
		tempNode = this.next;
		this.next = node;
		node.next = tempNode;
	}

?在n2后面插入一个节点n7

代码? ? ?输出结果

?2.循环链表

首节点和末节点被连接在一起的链表

?

(1).循环链表基本知识和使用

public class LoopNode {
	//节点存储的数据
	int data;
	//循环链表的特别之处,单链表中是Node next;就可
	LoopNode next = this;
	
	public LoopNode(int data) {
		this.data = data;
	}
	
	//返回下一个节点
	public LoopNode next() {
		return this.next;
	}
	
	//删除下一个节点
	public void remove() {
		//先取得下下个节点的值
		LoopNode tempLoopNode = this.next.next;;
		//下下个节点赋值下个节点,达成删除原下一个节点的效果
		this.next = tempLoopNode;
	}
	
	//插入一个节点
	public void insert(LoopNode loopNode) {
		//tempLoopNode把下一个节点存起来
		LoopNode tempLoopNode = this.next;
		//把传进来的loopNode传给this.next
		this.next = loopNode;
		//传进来的loopNode的下一个节点为一开始存的原先的下一个节点
		loopNode.next = tempLoopNode;
	}
	
	//获得节点的data值
	public int getData() {
		return this.data;
	}
}

测试循环双链表

//测试双向循环链表
public class Test {
	public static void main(String[] args) {
		LoopNode l1 = new LoopNode(11);
		LoopNode l2 = new LoopNode(22);
		LoopNode l3 = new LoopNode(33);
		LoopNode l4 = new LoopNode(44);
		l1.insert(l2);
		l2.insert(l3);
		l3.insert(l4);
		System.out.println(l3.next().getData());    //输出结果:44,即l4
		System.out.println(l4.next().getData());	//输出结果:11,即l1
		System.out.println(l1.next().getData());	//输出结果:22,即l2
		System.out.println(l2.next().getData());	//输出结果:33,即l3
	}	
}

3.双向循环链表

首节点和末节点被连接在一起的链表,并且双向循环链表的节点不仅包含指向下一个节点的指针 (next),还包含指向前一个节点的指针 (pre)

?(1)双向循环链表基本知识和使用

/*
 * 实现双向循环链表
 * 思路:在DoubleNode里面有指向下一个节点的next 和指向上一个节点的 pre
 */
public class DoubleNode {
//	存储节点的内容
	int data;
//	下一个节点的地址
	DoubleNode next = this;
//	上一个节点的地址
	DoubleNode pre = this;
	
//	构造器初始化,形参赋值给data
	public DoubleNode(int data) {
		this.data = data;
	}
	
//	获取下一个节点
	public DoubleNode next() {
		return this.next;
	}
	
//	获取上一个节点
	public DoubleNode pre() {
		return this.pre;
	}
	
//	获取节点的数据
	public int getData() {
		return this.data;
	}
	
//	在节点后面插入一个节点
	public DoubleNode after(DoubleNode afterNode) {
		//暂存原当前节点的下一个节点
		DoubleNode tempNode = this.next;
		//进行当前节点后面插入节点的操作,即当前节点的下一个节点为新插入的afterNode节点
		this.next = afterNode;
		//插入后的afterNode的前一个节点为当前节点
		afterNode.pre = this;
		
		//原当前节点的下一个节点tempNode,现在是afterNode的下一个节点
		afterNode.next = tempNode;
		//现在tempNode的前一个节点为afterNode
		tempNode.pre = afterNode;
		
		//设为void也可以,这里返回插入节点的那个对象,
        //是为了方便测试的时候用链式编程即n1.after(n2).after(n3)....这些
		return afterNode;
	}
}

测试循环双链表类

public class Test {
	public static void main(String[] args) {
		DoubleNode n1 = new DoubleNode(11);
		DoubleNode n2 = new DoubleNode(22);
		DoubleNode n3 = new DoubleNode(33);
		DoubleNode n4 = new DoubleNode(44);
		
//		n1.after(n2);
//		n2.after(n3);
//		n3.after(n4);
		n1.after(n2).after(n3).after(n4);
		
		System.out.println(n1.next().getData());	//n1的下一个节点n2
		System.out.println(n1.next().next().getData());	//n1的下下个节点n3
		System.out.println(n1.next().next().next().getData());	//n1的下下下个节点n4
		System.out.println(n4.next().getData());	//n4的下一个节点n1
		System.out.println(n1.pre().getData());//n1的前一个节点	n4
		System.out.println(n4.pre().getData());//n4的前一个节点	n3

	}
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-04 13:41:40  更:2022-01-04 13:43:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:34:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码