Java单链表增删查改操作
声明
此文章为
个人笔记文
,写的都是个人理解,如有哪里有误,还望大佬们指正
。
链表描述 - 百度百科
链表是一种
物理
存储单元
上非连续、非顺序的存储结构
,数据元素
的逻辑顺序是通过链表中的指针
链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素
的数据域,另一个是存储下一个结点地址的指针
域。 相比于线性表顺序结构
,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)
的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)
和O(1)
。使用链表结构可以克服
数组
链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组
随机读取的优点,同时链表由于增加了结点的指针
域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表
,双向链表
以及循环链表
。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。
描述总结
-
结构
链表是一种
物理
存储单元
上非连续、非顺序的存储结构
。 -
组成
链表由一系列结点(链表中每一个元素称为结点)组成。
-
链表类型
单向链表、双向链表、循环链表
单向链表实现
单向链表结构
单向链表的增删查改操作
具体功能实现方法如下图:
Linked 类准备
/**
* 单向链表
* head last
* -------------- -------------- -------------- --------------
* | data | next | --> | data | next | --> | data | next | ... --> | data | null |
* -------------- -------------- -------------- --------------
*/
public class Linked<T> {
/**
* 头结点
*/
private Node head;
/**
* 覆写 Object.toString 方法, 方便输出
* @return 链表数据组成的字符串, 格式如: [data1, data2, data3,...,dataN]
*/
@Override
public String toString() {
StringBuffer text = new StringBuffer();
Node pNode = this.head;
while (pNode != null) {
text.append(",").append(pNode.data);
pNode = pNode.next;
}
if (text.length() > 0) {
text.deleteCharAt(0);
}
return "Linked[" + text.toString() +']';
}
/**
* 节点
*/
class Node{
/**
* 节点存放的元素(数据)
*/
T data;
/**
* 节点指向的下一个节点
*/
Node next;
/**
* 根据元素进行构造节点
* @param data 元素
*/
public Node(T data) {
this(data, null);
}
/**
* 根据元素和下一个节点进行构造节点
* @param data 元素
* @param next 下一个节点
*/
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
}
新增操作
addHead(T data) 新增为头节点
/**
* 增加头结点
* 1. 当前元素节点下一个节点 指向 之前头节点
* 2. 头结点 指向 当前元素节点
* @param data 元素
* @return true: 成功; false: 失败
*/
public boolean addHead (T data) {
Node newNode = new Node(data);
newNode.next = head;
head = newNode;
return true;
}
add(int index, T data) 在指定的位置新增节点
/**
* 向 链表 某个位置添加节点
* @param index 位置
* @param data 元素
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean add (int index, T data) {
// 索引为 0, 则增加为头节点
if (index == 0) {
return this.addHead(data);
}
// 根据 索引位置 寻找到该节点的前一个节点
Node frontNode = this.head;
for (int i = 1; i < index; i++) {
frontNode = frontNode.next;
// 找不到,则返回false --> 失败
if (frontNode == null) {
return false;
}
}
// 1. 根据 前一个节点的下个节点 得到 索引位置对应的节点
// 2. 前一个节点的下个节点 指向 当前添加的元素节点
// 3. 当前添加的元素节点下个节点 指向 索引位置对应的节点
Node nextNode = frontNode.next;
Node newNode = new Node(data);
frontNode.next = newNode;
newNode.next = nextNode;
return true;
}
addLast(T data) 新增为最后一个节点(尾节点)
/**
* 向链表最后添加元素节点
* @param data 元素
* @return true: 成功; false: 失败
*/
public boolean addLast (T data) {
// 头节点为空, 则增加为头节点
if (this.head == null) {
return this.addHead(data);
}
// 寻找最后一个节点
Node lastNode = this.head;
while (lastNode != null) {
// 下一个节点为空, 则表示尾节点
if (lastNode.next == null) {
break;
}
lastNode = lastNode.next;
}
// 最后节点 下一个节点 指向 添加的元素节点
lastNode.next = new Node(data);
return true;
}
查询操作
getHead(T data) 获取头节点的元素数据
/**
* 获取头结点的元素
* @return null(在链表为空时会失败) 或 头结点的元素
*/
public T getHead() {
return this.isEmpty() ? null : this.head.data;
}
get(int index, T data) 获取指定位置节点的元素数据
/**
* 根据 索引位置获取元素
* @param index 索引位置
* @return null 或 索引位置对应的结点的元素
*/
public T get(int index) {
// 索引为0, 直接获取头结点元素
if (index == 0) {
return this.getHead();
}
// 获取索引位置对应的节点,当索引位置超出,则返回为null
// 循环从
Node pNode = this.head;
for (int i = 1; i <= index; i++) {
pNode = pNode.next;
// 索引位置超出, 直接返回 null
if (pNode == null) {
return null;
}
}
return pNode.data;
}
getLast(T data) 获取最后一个节点的元素数据
/**
* 获取链表尾节点元素
* @return null(在找不到节点时会失败) 或 尾节点的元素
*/
public T getLast() {
if (this.isEmpty()) {
return null;
}
// 循环寻找尾节点, 如果有节点的下一个节点为空, 则代表该节点为尾结点
Node lastNode = this.head;
while (lastNode != null) {
if (lastNode.next == null) {
break;
}
lastNode = lastNode.next;
}
return lastNode.data;
}
删除操作
removeHead() 删除头节点
/**
* 删除头结点
* @return true: 成功; false: 失败(在头节点为空时会失败)
*/
public boolean removeHead() {
if (this.isEmpty()) {
return false;
}
this.head = this.head.next;
return true;
}
remove(int index) 删除指定位置的节点
/**
* 根据索引位置删除节点
* @param index 索引位置
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean remove(int index) {
// 当索引位置为0, 删除头结点
if (index == 0) {
return this.removeHead();
}
// 根据索引位置找到 需要删除的节点 的前一个节点
Node frontNode = this.head;
for (int i = 1; i < index; i++) {
frontNode = frontNode.next;
// 索引位置还没遍历完,节点下一个节点 为空, 直接返回false
if (frontNode == null) {
return false;
}
}
// 将 需要删除的节点 的前一个节点 指向 需要删除的节点 的下一个节点
Node next = frontNode.next;
frontNode.next = next.next;
return true;
}
remove(T data) 根据元素删除节点
/**
* 根据元素删除节点
* @param data 元素
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean remove (T data) {
// 链表为空, 返回删除失败
if (this.isEmpty()) {
return false;
}
// 如果头节点恰巧和元素一样, 则删除头元素
if (this.head.data.equals(data)) {
return this.removeHead();
}
// 根据元素找到 需要删除的节点 的前一个节点
Node frontNode = this.head;
Node pNode = frontNode.next;
while (pNode != null) {
// 找到了元素对应的节点, 然后将 需要删除的节点 的前一个节点 指向 需要删除的节点 的下一个节点
if (pNode.data.equals(data)) {
frontNode.next = pNode.next;
return true;
}
// 记录前一个节点 和 循环查找 需要删除的节点
frontNode = pNode;
pNode = pNode.next;
}
// 找不到 需要删除的节点, 返回false, 代表失败
return false;
}
removeLast() 删除最后一个节点(尾节点)
/**
* 删除尾结点
* @return true: 成功; false: 失败(在找不到尾节点时会失败)
*/
public boolean removeLast() {
// 链表为空 或 没有尾结点, 返回false, 代表失败
if (this.isEmpty()) {
return false;
}
// 寻找 尾节点 的 前一个节点,然后将该节点一下个节点指向为空
Node frontNode = this.head;
Node pNode = frontNode.next;
while (pNode != null) {
pNode = pNode.next;
if (pNode != null) {
frontNode = frontNode.next;
}
}
frontNode.next = null;
return true;
}
修改操作
setHead(T data) 修改头节点元素数据
/**
* 重新 设置头节点的元素
* @param data 新的元素
* @return true: 成功; false: 失败(在找不到头节点时会失败)
*/
public boolean setHead (T data) {
if (this.isEmpty()) {
return false;
}
head.data = data;
return true;
}
set(int index, T data) 修改指定节点元素数据
/**
* 根据索引位置 设置 节点的元素
* @param index 索引位置
* @param data 元素
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean set (int index, T data) {
// 如果索引为0, 则进行设置头结点元素
if (index == 0) {
return this.setHead(data);
}
// 寻找到需要修改元素的节点;
// 如果在寻找时, 节点为空, 则代表没有该索引位置节点, 直接返回false
Node pNode = this.head;
for (int i = 1; i <= index; i++) {
pNode = pNode.next;
if (pNode == null) {
return false;
}
}
// 修改节点元素
pNode.data = data;
return true;
}
setLast(T data)修改最后一个节点(尾节点)元素数据
/**
* 设置尾结点元素
* @param data 新的元素
* @return true: 成功; false: 失败(在找不到尾节点时会失败)
*/
public boolean setLast (T data) {
// 如果链表为空, 直接返回false
if (this.isEmpty()) {
return false;
}
// 寻找尾节点, 然后进行设置节点元素值为新的元素
Node lastNode = this.head;
while (lastNode.next != null) {
lastNode = lastNode.next;
}
lastNode.data = data;
return true;
}
其他操作
contains(T data) 判断链表是否包含对应的元素数据
/**
* 判断链表是否包含对应的元素数据
* @param data 元素
* @return true : 不包含; false : 包含
*/
public boolean contains(T data) {
// 如果链表为空, 直接返回false
if (this.isEmpty()) {
return false;
}
// 从头节点开始遍历,如果匹配上则返回true, 匹配不上, 返回false
Node pNode = this.head;
while (pNode != null) {
if (pNode.data.equals(data)) {
return true;
}
pNode = pNode.next;
}
return false;
}
isEmpty() 判断链表是否为空
/**
* 判断链表是否为空
* @return true: 为空; false: 不为空
*/
public boolean isEmpty() {
return this.head == null;
}
测试
代码
public class LinkedTest {
public static void main(String[] args) {
Linked<Integer> intLinked = new Linked<>();
System.out.println("----------------- 测试 链表新增操作start -----------------");
// 测试空链表时 新增头节点
intLinked.addHead(-1);
System.out.println("空链表时 新增头节点 intLinked.addHead(-1) -> " + intLinked);
// 测试新增节点位置为0 -> 新增头节点
intLinked.add(0, 1);
System.out.println("新增节点位置为0 -> 新增头节点 intLinked.add(0, 1) -> " + intLinked);
// 测试链表不为时 新增头节点
intLinked.addHead(0);
System.out.println("试链表不为时 新增头节点 intLinked.addHead(0) -> " + intLinked);
// 测试 新增尾节点
intLinked.addLast(2);
System.out.println("新增尾节点 intLinked.addLast(2) -> " + intLinked);
System.out.println("----------------- 测试 链表新增操作end -----------------\n");
System.out.println("----------------- 测试 链表查询操作start -----------------");
// 测试 新增指定位置节点
intLinked.add(3, 3);
intLinked.add(4, 4);
System.out.println("新增指定位置节点 intLinked.add(3, 3);intLinked.add(4, 4); -> " + intLinked);
// 测试 获取头结点元素数据
System.out.println("获取头结点元素数据 intLinked.getHead() -> " + intLinked.getHead());
// 测试 获取指定位置结点元素数据
System.out.println("获取指定位置结点元素数据 intLinked.get(1) -> " + intLinked.get(1));
// 测试 获取指定位置结点元素数据(不存在的节点)
System.out.println("获取指定位置结点元素数据(不存在的节点) intLinked.get(9) -> " + intLinked.get(9));
// 测试 获取尾结点元素数据
System.out.println("获取尾结点元素数据 intLinked.getLast() -> " + intLinked.getLast());
System.out.println("----------------- 测试 链表查询操作end -----------------\n");
System.out.println("----------------- 测试 链表删除操作start -----------------");
// 测试 删除头节点
System.out.println("删除头节点 intLinked.removeHead() -> " + intLinked.removeHead() + "; 链表: " + intLinked);
// 测试 删除指定位置节点
System.out.println("删除指定位置节点 intLinked.remove(1) -> " + intLinked.remove(1) + "; 链表: " + intLinked);
// 测试 删除指定位置节点(不存在的节点)
System.out.println("删除指定位置节点(不存在的节点) intLinked.remove(9) -> " + intLinked.remove(9) + "; 链表: " + intLinked);
// 测试 删除指定元素节点
System.out.println("删除指定元素节点 intLinked.remove(new Integer(3)) -> " + intLinked.remove(new Integer(3)) + "; 链表: " + intLinked);
// 测试 删除尾节点
System.out.println("删除尾节点 intLinked.removeLast() -> " + intLinked.removeLast() + "; 链表: " + intLinked);
System.out.println("----------------- 测试 链表删除操作end -----------------\n");
System.out.println("----------------- 测试 链表修改操作start -----------------");
// 测试 修改头节点
System.out.println("修改头节点 intLinked.setHead(-2) -> " + intLinked.setHead(-2)+ "; 链表: " + intLinked);
// 测试 修改指定位置节点
System.out.println("修改指定位置节点 intLinked.set(1, 0) -> " + intLinked.set(1, 0) + "; 链表: " + intLinked);
// 测试 修改指定位置节点(不存在的节点)
System.out.println("修改指定位置节点(不存在的节点) intLinked.set(9, 8) -> " + intLinked.set(9, 8) + "; 链表: " + intLinked);
// 测试 修改尾节点
System.out.println("修改尾节点 intLinked.setLast(666) -> " + intLinked.setLast(666) + "; 链表: " + intLinked);
System.out.println("----------------- 测试 链表修改操作end -----------------\n");
System.out.println("----------------- 测试 链表其他操作start -----------------");
// 测试 链表是否包含该元素
System.out.println("链表是否包含该元素 intLinked.contains(666) -> " + intLinked.contains(666) + "; 链表: " + intLinked);
// 测试 链表是否包含该元素(不存在的元素)
System.out.println("链表是否包含该元素(不存在的元素) intLinked.contains(777) -> " + intLinked.contains(7777) + "; 链表: " + intLinked);
// 测试 链表是否为空
Linked<String> strLinked = new Linked<>();
System.out.println("链表是否为空 strLinked.isEmpty() -> " + strLinked.isEmpty() + "; 链表: " + strLinked);
// 测试 链表是否为空(不为空)
strLinked.add(0, "Hello");
System.out.println("链表是否为空(不为空) strLinked.isEmpty() -> " + strLinked.isEmpty() + "; 链表: " + strLinked);
System.out.println("----------------- 测试 链表其他操作end -----------------");
}
}
测试结果
----------------- 测试 链表新增操作start -----------------
空链表时 新增头节点 intLinked.addHead(-1) -> Linked[-1]
新增节点位置为0 -> 新增头节点 intLinked.add(0, 1) -> Linked[1,-1]
试链表不为时 新增头节点 intLinked.addHead(0) -> Linked[0,1,-1]
新增尾节点 intLinked.addLast(2) -> Linked[0,1,-1,2]
----------------- 测试 链表新增操作end -----------------
----------------- 测试 链表查询操作start -----------------
新增指定位置节点 intLinked.add(3, 3);intLinked.add(4, 4); -> Linked[0,1,-1,3,4,2]
获取头结点元素数据 intLinked.getHead() -> 0
获取指定位置结点元素数据 intLinked.get(1) -> 1
获取指定位置结点元素数据(不存在的节点) intLinked.get(9) -> null
获取尾结点元素数据 intLinked.getLast() -> 2
----------------- 测试 链表查询操作end -----------------
----------------- 测试 链表删除操作start -----------------
删除头节点 intLinked.removeHead() -> true; 链表: Linked[1,-1,3,4,2]
删除指定位置节点 intLinked.remove(1) -> true; 链表: Linked[1,3,4,2]
删除指定位置节点(不存在的节点) intLinked.remove(9) -> false; 链表: Linked[1,3,4,2]
删除指定元素节点 intLinked.remove(new Integer(3)) -> true; 链表: Linked[1,4,2]
删除尾节点 intLinked.removeLast() -> true; 链表: Linked[1,4]
----------------- 测试 链表删除操作end -----------------
----------------- 测试 链表修改操作start -----------------
修改头节点 intLinked.setHead(-2) -> true; 链表: Linked[-2,4]
修改指定位置节点 intLinked.set(1, 0) -> true; 链表: Linked[-2,0]
修改指定位置节点(不存在的节点) intLinked.set(9, 8) -> false; 链表: Linked[-2,0]
修改尾节点 intLinked.setLast(666) -> true; 链表: Linked[-2,666]
----------------- 测试 链表修改操作end -----------------
----------------- 测试 链表其他操作start -----------------
链表是否包含该元素 intLinked.contains(666) -> true; 链表: Linked[-2,666]
链表是否包含该元素(不存在的元素) intLinked.contains(777) -> false; 链表: Linked[-2,666]
链表是否为空 strLinked.isEmpty() -> true; 链表: Linked[]
链表是否为空(不为空) strLinked.isEmpty() -> false; 链表: Linked[Hello]
----------------- 测试 链表其他操作end -----------------
单向链表实现全部代码
/**
* 单向链表
* head last
* -------------- -------------- -------------- --------------
* | data | next | --> | data | next | --> | data | next | ... --> | data | null |
* -------------- -------------- -------------- --------------
*/
public class Linked<T> {
/**
* 头结点
*/
private Node head;
/**
* 增加头结点
* 1. 当前元素节点下一个节点 指向 之前头节点
* 2. 头结点 指向 当前元素节点
* @param data 元素
* @return true: 成功; false: 失败
*/
public boolean addHead (T data) {
Node newNode = new Node(data);
newNode.next = head;
head = newNode;
return true;
}
/**
* 向 链表 某个位置添加节点
* @param index 位置
* @param data 元素
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean add (int index, T data) {
// 索引为 0, 则增加为头节点
if (index == 0) {
return this.addHead(data);
}
// 根据 索引位置 寻找到该节点的前一个节点
Node frontNode = this.head;
for (int i = 1; i < index; i++) {
frontNode = frontNode.next;
// 找不到,则返回false --> 失败
if (frontNode == null) {
return false;
}
}
// 1. 根据 前一个节点的下个节点 得到 索引位置对应的节点
// 2. 前一个节点的下个节点 指向 当前添加的元素节点
// 3. 当前添加的元素节点下个节点 指向 索引位置对应的节点
Node nextNode = frontNode.next;
Node newNode = new Node(data);
frontNode.next = newNode;
newNode.next = nextNode;
return true;
}
/**
* 向链表最后添加元素节点
* @param data 元素
* @return true: 成功; false: 失败
*/
public boolean addLast (T data) {
// 头节点为空, 则增加为头节点
if (this.head == null) {
return this.addHead(data);
}
// 寻找最后一个节点
Node lastNode = this.head;
while (lastNode != null) {
// 下一个节点为空, 则表示尾节点
if (lastNode.next == null) {
break;
}
lastNode = lastNode.next;
}
// 最后节点 下一个节点 指向 添加的元素节点
lastNode.next = new Node(data);
return true;
}
/**
* 获取头结点的元素
* @return null(在链表为空时会失败) 或 头结点的元素
*/
public T getHead() {
return this.isEmpty() ? null : this.head.data;
}
/**
* 根据 索引位置获取元素
* @param index 索引位置
* @return null 或 索引位置对应的结点的元素
*/
public T get(int index) {
// 索引为0, 直接获取头结点元素
if (index == 0) {
return this.getHead();
}
// 获取索引位置对应的节点,当索引位置超出,则返回为null
// 循环从
Node pNode = this.head;
for (int i = 1; i <= index; i++) {
pNode = pNode.next;
// 索引位置超出, 直接返回 null
if (pNode == null) {
return null;
}
}
return pNode.data;
}
/**
* 获取链表尾节点元素
* @return null(在找不到节点时会失败) 或 尾节点的元素
*/
public T getLast() {
if (this.isEmpty()) {
return null;
}
// 循环寻找尾节点, 如果有节点的下一个节点为空, 则代表该节点为尾结点
Node lastNode = this.head;
while (lastNode != null) {
if (lastNode.next == null) {
break;
}
lastNode = lastNode.next;
}
return lastNode.data;
}
/**
* 删除头结点
* @return true: 成功; false: 失败(在头节点为空时会失败)
*/
public boolean removeHead() {
if (this.isEmpty()) {
return false;
}
this.head = this.head.next;
return true;
}
/**
* 根据索引位置删除节点
* @param index 索引位置
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean remove(int index) {
// 当索引位置为0, 删除头结点
if (index == 0) {
return this.removeHead();
}
// 根据索引位置找到 需要删除的节点 的前一个节点
Node frontNode = this.head;
for (int i = 1; i < index; i++) {
frontNode = frontNode.next;
// 索引位置还没遍历完,节点下一个节点 为空, 直接返回false
if (frontNode == null) {
return false;
}
}
// 将 需要删除的节点 的前一个节点 指向 需要删除的节点 的下一个节点
Node next = frontNode.next;
frontNode.next = next.next;
return true;
}
/**
* 根据元素删除节点
* @param data 元素
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean remove (T data) {
// 链表为空, 返回删除失败
if (this.isEmpty()) {
return false;
}
// 如果头节点恰巧和元素一样, 则删除头元素
if (this.head.data.equals(data)) {
return this.removeHead();
}
// 根据元素找到 需要删除的节点 的前一个节点
Node frontNode = this.head;
Node pNode = frontNode.next;
while (pNode != null) {
// 找到了元素对应的节点, 然后将 需要删除的节点 的前一个节点 指向 需要删除的节点 的下一个节点
if (pNode.data.equals(data)) {
frontNode.next = pNode.next;
return true;
}
// 记录前一个节点 和 循环查找 需要删除的节点
frontNode = pNode;
pNode = pNode.next;
}
// 找不到 需要删除的节点, 返回false, 代表失败
return false;
}
/**
* 删除尾结点
* @return true: 成功; false: 失败(在找不到尾节点时会失败)
*/
public boolean removeLast() {
// 链表为空 或 没有尾结点, 返回false, 代表失败
if (this.isEmpty()) {
return false;
}
// 寻找 尾节点 的 前一个节点,然后将该节点一下个节点指向为空
Node frontNode = this.head;
Node pNode = frontNode.next;
while (pNode != null) {
pNode = pNode.next;
if (pNode != null) {
frontNode = frontNode.next;
}
}
frontNode.next = null;
return true;
}
/**
* 重新 设置头节点的元素
* @param data 新的元素
* @return true: 成功; false: 失败(在找不到头节点时会失败)
*/
public boolean setHead (T data) {
if (this.isEmpty()) {
return false;
}
head.data = data;
return true;
}
/**
* 根据索引位置 设置 节点的元素
* @param index 索引位置
* @param data 元素
* @return true: 成功; false: 失败(在找不到节点时会失败)
*/
public boolean set (int index, T data) {
// 如果索引为0, 则进行设置头结点元素
if (index == 0) {
return this.setHead(data);
}
// 寻找到需要修改元素的节点;
// 如果在寻找时, 节点为空, 则代表没有该索引位置节点, 直接返回false
Node pNode = this.head;
for (int i = 1; i <= index; i++) {
pNode = pNode.next;
if (pNode == null) {
return false;
}
}
// 修改节点元素
pNode.data = data;
return true;
}
/**
* 设置尾结点元素
* @param data 新的元素
* @return true: 成功; false: 失败(在找不到尾节点时会失败)
*/
public boolean setLast (T data) {
// 如果链表为空, 直接返回false
if (this.isEmpty()) {
return false;
}
// 寻找尾节点, 然后进行设置节点元素值为新的元素
Node lastNode = this.head;
while (lastNode.next != null) {
lastNode = lastNode.next;
}
lastNode.data = data;
return true;
}
/**
* 判断链表是否包含对应的元素数据
* @param data 元素
* @return true : 不包含; false : 包含
*/
public boolean contains(T data) {
// 如果链表为空, 直接返回false
if (this.isEmpty()) {
return false;
}
// 从头节点开始遍历,如果匹配上则返回true, 匹配不上, 返回false
Node pNode = this.head;
while (pNode != null) {
if (pNode.data.equals(data)) {
return true;
}
pNode = pNode.next;
}
return false;
}
/**
* 判断链表是否为空
* @return true: 为空; false: 不为空
*/
public boolean isEmpty() {
return this.head == null;
}
/**
* 覆写 Object.toString 方法, 方便输出
* @return 链表数据组成的字符串, 格式如: [data1, data2, data3,...,dataN]
*/
@Override
public String toString() {
StringBuffer text = new StringBuffer();
Node pNode = this.head;
while (pNode != null) {
text.append(",").append(pNode.data);
pNode = pNode.next;
}
if (text.length() > 0) {
text.deleteCharAt(0);
}
return "Linked[" + text.toString() +']';
}
/**
* 节点
*/
class Node{
/**
* 节点存放的元素(数据)
*/
T data;
/**
* 节点指向的下一个节点
*/
Node next;
/**
* 根据元素进行构造节点
* @param data 元素
*/
public Node(T data) {
this(data, null);
}
/**
* 根据元素和下一个节点进行构造节点
* @param data 元素
* @param next 下一个节点
*/
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
}