Java数据结构和算法(一)线性结构之单链表
Java数据结构和算法(一)线性结构之单链表
prev current next
-------------- -------------- --------------
| value | next | -> | value | next | -> | value | next |
-------------- -------------- --------------
单链表的结构如上:最后一个节点的 next=null。下面看一下代码。
(1) 链表的基本操作
public class Node<E> {
private E value;
private Node next;
public Node(E value) {
this.value = value;
}
// 追加到最后一个元素
public Node append(Node node) {
Node tail = tail();
tail.next(node);
return this;
}
// 删除指定的节点
public void remove(Node node) {
Node prev = prev(node);
if (prev != null) {
prev.next = node.next;
}
}
// 节点总数
public int size() {
int size = 1;
Node current = this;
while (current.next != null) {
size++;
current = current.next;
}
return size;
}
// 查找指定节点的上一个节点
public Node prev(Node node) {
Node prev = this;
while (prev != null) {
if (prev.next == node) {
return prev;
}
prev = prev.next;
}
return null;
}
// 查找尾节点,单链表 tail.next=null
public Node tail() {
Node tail = this;
while (tail.next != null) {
tail = tail.next;
}
return tail;
}
// 设置当前节点的下一个节点
public void next(Node next) {
// 设置该节点的后继节点
next.next = this.next;
// 将该节点设置为当前节点的前驱节点
this.next = next;
}
public Node next() {
return next;
}
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
}
(2) 取出中间节点
偶数节点取中间两个节点的前一个节点,奇数节点取正中间的节点
public Node mid() {
Node stepOneNode = this;
Node stepTwoNode = this;
while (stepTwoNode != null) {
stepTwoNode = stepTwoNode.next;
if (stepTwoNode != null) {
stepTwoNode = stepTwoNode.next;
if (stepTwoNode != null) {
stepOneNode = stepOneNode.next;
}
}
}
return stepOneNode;
}
(3) 链表反转
public Node reverse() {
Node prev = null;
Node next = null;
Node current = this;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
测试一把:
public void test1() {
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
n1.append(n2).append(n3);
Assert.assertEquals(3, n1.next().next().getValue());
Assert.assertEquals(3, n1.tail().getValue());
Assert.assertEquals(2, n1.prev(n3).getValue());
Assert.assertEquals(3, n1.size());
n1.remove(n2);
Assert.assertEquals(3, n1.next().getValue());
Assert.assertEquals(1, n1.mid().getValue());
n1.next(n2);
Assert.assertEquals(3, n1.next().next().getValue());
Assert.assertEquals(2, n1.mid().getValue());
Node reverse = n1.reverse();
Assert.assertEquals(3, reverse.getValue());
Assert.assertEquals(2, reverse.next().getValue());
Assert.assertEquals(1, reverse.next().next().getValue());
}
(4) 有序链表的合并
两个有序链表合并后还是有序的,代码如下:
// 有序链表合并,两个链表均升序排列,最终的结果也升序排列
public static Node merge(Node<Integer> node1, Node<Integer> node2) {
if (node1 == null || node2 == null) {
return node1 == null ? node2 : node1;
}
Node<Integer> head = node1.value < node2.value ? node1 : node2;
Node<Integer> cur1 = head == node1 ? node1 : node2; // 小
Node<Integer> cur2 = head == node1 ? node2 : node1; // 大
Node prev = null; // curl1 的前驱节点,小
while (cur1 != null && cur2 != null) {
if (cur1.value < cur2.value) {
prev = cur1;
cur1 = cur1.next;
} else {
// 将 curl2 插入到 prev 和 curl1 之间
Node tmp = cur2.next;
cur2.next = cur1;
prev.next = cur2;
prev = cur2;
cur2 = tmp;
}
}
prev.next = cur1 == null ? cur2 : cur1;
return head;
}
// 有序链表合并,两个链表均升序排列,最终的结果也升序排列
public static Node mergeRecurse(Node<Integer> node1, Node<Integer> node2) {
if (node1 == null || node2 == null) {
return node1 != null ? node1 : node2;
}
Node head = null;
if (node1.value > node2.value) {
head = node2;
head.next = mergeRecurse(node1, node2.next);
} else {
head = node1;
head.next = mergeRecurse(node1.next, node2);
}
return head;
}
测试:
public void mergeTest() {
Node n1 = new Node(1);
// 省略...
Node n6 = new Node(6);
n1.append(n3).append(n5);
n2.append(n4).append(n6);
Node merge1 = Node.merge(n1, n2);
//Node merge1 = Node.mergeRecurse(n1, n2);
Assert.assertEquals(6, merge1.size());
Assert.assertEquals(2, merge1.next().getValue());
}
每天用心记录一点点。内容也许不重要,但习惯很重要!
Java数据结构和算法(一)线性结构之单链表的更多相关文章
- [数据结构 - 第3章] 线性表之单链表(C++实现)
一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...
- Java数据结构与算法(1):线性表
线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列.形如如A0,A1,...,An-1.大小为0的表为空表,称Ai后继Ai-1,并称Ai-1前驱Ai. printList打印出表 ...
- Java数据结构和算法(一)线性结构
Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
- java数据结构与算法之栈(Stack)设计与实现
本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...
- Java数据结构和算法 - 二叉树
前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...
- Java数据结构和算法 - 数组
Q: 数组的创建? A: Java中有两种数据类型,基本类型和对象类型,在许多编程语言中(甚至面向对象语言C++),数组也是基本类型.但在Java中把数组当做对象来看.因此在创建数组时,必须使用new ...
- Java数据结构和算法(一)树
Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
随机推荐
- mac mysql中文乱码问题
God,今天看了好多资料,除了让我命令更熟练以外浪费了好多时间. 遇到的问题:写入数据库有中文的时候,显示??? 最后解决办法: 1.打开终端,输入: mysql -u root -p,然后输入mys ...
- Python之模块(一)
模块 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护.为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少 ...
- OpenCL 图像卷积 3 使用 CPU
▶ CPU 图像卷积,共四种方法.分别为基本串行,使用模板,使用局部内存,使用AVX指令优化 ● 全部的代码,仅在主函数中选择调用的函数名即可. #include <stdio.h> #i ...
- JAVA Spring 面向切面编程 基本案例(AOP)
< 1 > 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...
- leetcode412
public class Solution { public IList<string> FizzBuzz(int n) { var list = new List<string&g ...
- 2.vo传参模式和ModerDriven传参模式
转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html Copy上面的myStruts2项目,改名为myStruts2Vo项目.作如 ...
- 不丢失log的情况下迁移git空间
背景: 原来的源码都放在个人的空间下,为了团队后续规范管理,建立了一个团队使用的空间,需要把旧空间的文件和提交记录,一起迁移. 方法:git remote 进行空间切换 1.查看当前空间名:git r ...
- UI5-文档-4.23-Custom Formatters
如果希望对数据模型的属性进行更复杂的格式化逻辑,还可以编写自定义格式化函数.现在我们将使用自定义格式化程序添加本地化状态,因为数据模型中的状态是一种相当技术性的格式. Preview A status ...
- vue 引入bootstarp --webpack
注意对应好版本 - 稳定版本 :"bootstrap": "^3.0.0" 否则样式异常, 1.npm install jquery --save-dev 引 ...
- Jenkins服务器磁盘空间爆满问题解决
现象: 从根目录开始,使用du -h -x --max-depth=1 查看哪个目录占用过高,打算对于过高目录中的内容适当删减腾出一些空间 通过追踪查询,发现是jenkins的构建纪录未清理,而且最 ...