Java实现单链表

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

目录

  • 链表

      • 单链表示意图:
  • 链表节点定义:

  • 单链表的操作:

    • 1.单链表的打印
  • 2.头插法

  • 3.尾插法

  • 4.任意位置插入

  • 5.查找关键字key是否在单链表中

  • 6.删除第一次出现关键字为key的节点

  • 7.删除所有值为key的节点

  • 8.得到单链表的长度

  • 9.单链表的清空

    • 附上全部代码:
  • **部分检验代码:**

链表

=============================================================

定义:

链表是一种物理存储结构上非连续存储结构,是Java数据结构中一种很基础很常见却也很重要的数据结构

数据元素的逻辑顺序是通过链表中的引用链接次序实现的

思考:如何把一组数据串起来?

对于单链表来说,它是由一个一个节点串起来的,而每一个节点的组成由数值域 (data域) 和下一个节点的引用 (next域) 组成

单链表示意图:

1.不带头节点的单向非循环链表:

在这里插入图片描述

2.带有头节点的单向非循环链表:

在这里插入图片描述

3.带有头节点的单向循环链表:

在这里插入图片描述

由上图,可得:

  • 链表不同于数组,链表是以结点的形式存储,在物理空间上不一定连续

  • 单链表是由节点组成的

  • 链表的每个节点的包含 data (数据)域,next (指针)域,指针域:指向下一个结点的位置

  • 带有头节点的单向非循环链表,头结点是不会发生改变的

而不带头节点的单向非循环链表的头节点可能会发生改变

  • 带有头节点的单向非循环链表,其头节点不可以被删除

  • 链表的头结点不存储数据,只是为了指向链表的开头

接下来的例子以不带头节点的单向非循环链表为例:

链表节点定义:


通过分析,每一个节点都是对象,都有两个属性,一个data,一个next

在这里,我们通过一个类来表示一个结点,在类中声明数据及下一个结点next

//节点类型

class Node{

//Node的两个属性

public int data; //0

public Node next; //null

//提供一个构造方法,实例化对象

public Node(int data){

this.data = data;

this.next = null;

}

}

单链表的操作:


1.单链表的打印

public void print(){

Node cur = this.head;

while(cur != null){

System.out.print(cur.data+" ");

cur = cur.next; //节点后移

}

}

若写成cur.next,则就少打印一个数

在这里插入图片描述

2.头插法

单链表插入的时候,要先绑后边

public void addFist(int data){

Node node = new Node(data);

node.next = this.head;

head = node;

}

头插法执行过程:

在这里插入图片描述

在这里插入图片描述

3.尾插法

public void addLast(int data){

Node node = new Node(data);

if(this.head == null){

this.head = node;

return;

}

Node last = this.head;

while (last.next != null){

last = last.next;

}

last.next = node;

}

尾插法关键的点在于"找尾巴"

在这里插入图片描述

在这里插入图片描述

4.任意位置插入

将第一个位置看成0号下标:

以插入2号位置为例:

  1. 首先定义一个 cur,走index-1步,找到 2 号位置的前一个(重点)

  2. 插入:先连接后边的值,再连接后边的值

node.next = cur.next;

cur.next = node;

  1. 若 index 为0,则相当于一个头插法

  2. 若 index 为 len-1,则相当于一个尾插法

public void addIndex(int index,int data){

Node node = new Node(data);

if(index == 0){

this.addFist(data);

return;

}

if(index == this.len()){

this.addLast(data);

return;

}

//需要找到index位置的前一个节点的地址

Node cur = searchIndex(index);

//插入

node.next = cur.next;

cur.next = node;

}

private Node searchIndex(int index){

//index合法性判定

if(index < 0 || index > this.len()){

throw new RuntimeException(“index位置不合法!”);

}

Node cur = this.head;

while(index-1 != 0){

cur = cur.next;

index–;

}

return cur;

}

在这里插入图片描述

5.查找关键字key是否在单链表中

public boolean contain(int key){

Node cur = this.head;

while (cur != null){

if(cur.data == key){

return true;

}

cur = cur.next;

}

return false;

}

6.删除第一次出现关键字为key的节点

public void deleteKey(int key){

if(this.head == null){

return;

}

//删除的是不是头节点

if(this.head.data == key){

this.head = this.head.next;

return;

}

//找到删除节点的前驱

Node tmp = searchTmp(key);

if(tmp == null){

System.out.println(“该节点不存在!”);

return;

}

Node del = tmp.next;

tmp.next = del.next;

}

//找要删除节点的前驱

private Node searchTmp(int key){

Node tmp = this.head;

while(tmp.next != null){

if(tmp.next.data == key){

return tmp;

}

else{

tmp = tmp.next;

}

}

return null;

}

  1. 首先定义一个 tmp,找到要删除节点的前一个位置

  2. 将后一个next覆盖给前一个,即:tmp.next = del.next

在这里插入图片描述

7.删除所有值为key的节点

public void deleteAllKey(int key){

Node tmp = this.head;

Node cur = this.head.next; //代表要删除的节点

while(cur != null){

if(cur.data == key){

tmp.next = cur.next;

cur = cur.next;

}

else {

tmp = cur;

cur = cur.next;

}

}

if(this.head.data == key){

this.head = this.head.next;

}

}

8.得到单链表的长度

public int len(){

int count = 0;

Node cur = this.head;

while (cur != null){

count++;

cur = cur.next;

}

return count;

}

9.单链表的清空

JVM 在回收内存的时候,当该对象没有人在引用它的时候,这个对象才会被回收

public void clear(){

this.head = null;

}

以上是单链表最基础的全部代码

附上全部代码:

//节点类型

class Node{

//Node的两个属性

public int data; //0

public Node next; //null

//提供一个构造方法,实例化对象

public Node(int data){

this.data = data;

this.next = null;

}

}

public class MyLinkedList {

//head 是 MyLinkedList的一个成员属性,代表整个链表的头

public Node head; //保存单链表头节点的引用 值默认为null

//1.打印单链表

public void print(){

Node cur = this.head;

while (cur != null){

System.out.print(cur.data+" ");

cur = cur.next; //节点后移

}

System.out.println();

}

//2.头插法

public void addFist(int data){

Node node = new Node(data);

node.next = this.head;

head = node;

}

//3.尾插法

public void addLast(int data){

Node node = new Node(data);

if(this.head == null){

this.head = node;

return;

}

Node last = this.head;

while (last.next != null){

last = last.next;

}

last.next = node;

}

//4.任意位置插入,第一个数据节点为0号下标

public void addIndex(int index,int data){

Node node = new Node(data);

if(index == 0){

this.addFist(data);

return;

}

if(index == this.len()){

写在最后

作为一名即将求职的程序员,面对一个可能跟近些年非常不同的 2019 年,你的就业机会和风口会出现在哪里?在这种新环境下,工作应该选择大厂还是小公司?已有几年工作经验的老兵,又应该如何保持和提升自身竞争力,转被动为主动?

就目前大环境来看,跳槽成功的难度比往年高很多。一个明显的感受:今年的面试,无论一面还是二面,都很考验Java程序员的技术功底。

最近我整理了一份复习用的面试题及面试高频的考点题及技术点梳理成一份“Java经典面试问题(含答案解析).pdf和一份网上搜集的“Java程序员面试笔试真题库.pdf”(实际上比预期多花了不少精力),包含分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货!

由于篇幅有限,为了方便大家观看,这里以图片的形式给大家展示部分的目录和答案截图!

Java经典面试问题(含答案解析)

阿里巴巴技术笔试心得

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
出现在哪里?在这种新环境下,工作应该选择大厂还是小公司?已有几年工作经验的老兵,又应该如何保持和提升自身竞争力,转被动为主动?

就目前大环境来看,跳槽成功的难度比往年高很多。一个明显的感受:今年的面试,无论一面还是二面,都很考验Java程序员的技术功底。

最近我整理了一份复习用的面试题及面试高频的考点题及技术点梳理成一份“Java经典面试问题(含答案解析).pdf和一份网上搜集的“Java程序员面试笔试真题库.pdf”(实际上比预期多花了不少精力),包含分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货!

由于篇幅有限,为了方便大家观看,这里以图片的形式给大家展示部分的目录和答案截图!
[外链图片转存中…(img-aZTnSRj8-1714684139362)]

Java经典面试问题(含答案解析)

[外链图片转存中…(img-LE36XaBJ-1714684139363)]

阿里巴巴技术笔试心得

[外链图片转存中…(img-g4rQykCr-1714684139363)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值