Java基础课 | 链表的基础操作I
- Java基础
- 构造方法
- 字符串、数组
- 缺点
- 链表
- 定义链表
- 插入操作
- 打印链表
- 题目
- 程序编写
Java基础
构造方法
使用自定义类时,若希望在new
的时候就为创建的实例赋值,如:
Person zs = new Person("张三", 18);
Person ls = new Person("李四", 20);
需要在类中实现构造方法。
- 构造方法的名称必须与所属类的名称完全相同。
- 构造方法没有返回类型。
class Person {
String name;
int age;
//构造方法,接受name和age参数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
其中,this
是一个关键字,表示当前示例,即,为当前示例的name
和age
赋值为传递的name
和age
。
字符串、数组
- 元素按照一定的顺序来排列
- 可以通过索引来访问数组中的元素和字符串中的字符
缺点
- 固定大小:数组的大小通常是固定的,一旦分配了内存空间,就难以动态地扩展或缩小。如果需要存储的元素数量超出了数组的大小,就需要重新分配更大的数组,并将原来数组的内容复制过去,需要执行很多额外的操作。
- 内存连续:当需要存储一些需要占用空间较大的内容,也只能找一些大块的内存区域,而空间较小的内存区域就被浪费了,从而导致内存资源浪费。
- 固定的数据类型:数组要求所有元素具有相同的数据类型,字符串存储的都是字符,无法存储不同类型的数据。
- 增删元素操作复杂:需要遍历、移位等操作,十分耗时。
链表
链表的元素在计算机中的存储可以是连续的,也可以是不连续的。每个数据元素(称之为节点
)除了存储本身的信息(data数据
)之外,还存储一个指示着下一个元素的地址信息(next指针
),就像这些元素被一条“链”串起来。
链表的第一个节点的存储位置被成为头节点,然后通过next指针
找到下一个节点,直到找到最后一个节点,最后一个节点的next指针
并不存在,也就是“空”的,在Java中,用null
来表示。
定义链表
在Java中,可以使用类来定义一个链表节点。由链表节点的概念,一个链表节点包含一个数据元素和一个指向下一个节点的引用,即包括一个数据字段和一个节点字段。
定义链表节点:
class Node {
int data; // 数据元素
Node next; // 指向下一个节点的引用next,类型是Node,实例名称为next
// 构造方法,初始化节点对象,参数为一个整数,表示节点的data字段
public Node(int data) {
this.data = data;// 初始化节点的data字段
this.next = null;// next字段初始化为null,表示新创建的节点没有下一个节点
定义链表:定义链表类,包括链表头节点和链表的节点数量这两个字段。
class LinkList {
// 私有变量,存储链表头节点
private Node headNode;
// 私有变量,存储链表长度
private int length;
// 链表的构造方法,用于初始化链表对象
public LinkList() {
// 构造链表时,头节点为null,表示链表开始时是空的
this.headNode = null;
// 没有初始化length,使用默认值0,表示链表长度为0
}
}
在Java中,一个类可以包含另一个类(内部类),内部类可以访问外部类的私有成员,将相关的类放在一起,可以使代码更具结构性和可读性。
将Node
类放在LinkList
类中,表明Node
类是LinkList
类的一部分。
class LinkList {
// 内部类,定义链表节点,同时它是public的,可以被外部类和其他类使用
public static class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
private Node headNode;
private int length;
public LinkList() {
this.headNode = null;
}
}
插入操作
定义一个方法,接收传入放入数据,并构建一个新的节点,插入到链表的尾部。具体步骤:
- 链表长度
length
+ 1 - 创建一个新的链表节点,初始化它的值为
data
- 如果当前链表为空链表(头节点为空 / 链表长度为0),则新创建的链表节点为头节点
- 如果当前链表不为空链表,将新的节点放入到链表的尾部,接入链表,也就是当前链表的尾部
next
指向新节点,新接入的链表节点变为链表的尾部。
public Node insert(int data) {
this.length++; // 链表长度加1
Node newNode = new Node(data); //创建一个新的链表节点
if (this.headNode == null) { // 如果当前链表为空链表
this.headNode = newNode; // 新创建的链表节点为头节点
} else { // 如果当前链表不是空链表
Node currentNode = this.headNode; // currentNode指针初始指向 新创建的链表节点为头节点
while (currentNode.next != null) {
// 不断移动currentNode,直到next指针为空时停止,说明已经走到最后一个节点
currentNode = currentNode.next;
}
currentNode.next = newNode;
}
return newNode; // 返回插入的节点
}
打印链表
打印链表节点,操作步骤和遍历链表直到找到最后一个节点的过程相似。
public void printLinkList() {
Node currentNode = headNode; //currentNode指针初始指向 头节点
while (currentNode != null) {
System.out.println(currentNode.data); // 输出链表数据
currentNode = currentNode.next; // 移动 currentNode
}
}
题目
题目描述
构建一个单向链表,链表中包含一组整数数据。输出链表中的所有元素。
要求
- 使用自定义的链表数据结构
- 提供一个 linkedList 类来管理链表,包含构建链表和输出链表元素的方法
- 在 main 函数中,创建一个包含一组整数数据的链表,然后调用链表的输出方法将所有元素打印出来
输入描述
包含多组测试数据,输入直到文件尾结束。
每组的第一行包含一个整数 n,表示需要构建的链表的长度。
接下来一行包含 n 个整数,表示链表中的元素。
输出描述
每组测试数据输出占一行。
按照顺序打印出链表中的元素,用空格隔开,最后一个元素后没有空格。
程序编写
先写基础的代码结构:
import java.util.Scanner
public class Main {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNextInt()) {
}
sc.close();
}
}
然后写定义的链表类和相关方法:
// 定义链表类
class LinkList{
// 定义链表节点
public static class Node {
int data;
Node next;
public Node(int data){
this.data = data;
this.next = null;
}
}
// 头节点
private Node headNode;
// 链表长度
private int length;
public LinkList() {
this.headNode = null;
}
//插入数据
public Node insert(int data) {
this.length++;
Node newNode = new Node(data);
if (this.headNode == null) {
this.headNode = newNode;
return this.headNode;
} else {
Node currentNode = this.headNode;
while (currentNode.next != null) {
currentNode = currentNode.next;
}
currentNode.next = newNode;
return newNode;
}
}
// 输出数据
public void printLinkList() {
Node currentNode = headNode;
while (currentNode != null) {
System.out.println(currentNode.data);
currentNode = currentNode.next;
}
}
}
再根据输入的值构建链表。
构建完成后,根据需求调用printLinkList
方法打印链表。
完整代码:
import java.util.*;
// 定义链表类
class LinkList{
// 定义链表节点
public static class Node {
int data;
Node next;
public Node(int data){
this.data = data;
this.next = null;
}
}
// 头节点
private Node headNode;
// 链表长度
private int length;
public LinkList() {
this.headNode = null;
}
//插入数据
public Node insert(int data) {
this.length++;
Node newNode = new Node(data);
if (this.headNode == null) {
this.headNode = newNode;
return this.headNode;
} else {
Node currentNode = this.headNode;
while (currentNode.next != null) {
currentNode = currentNode.next;
}
currentNode.next = newNode;
return newNode;
}
}
// 输出数据
public void printLinkList() {
Node currentNode = headNode;
while (currentNode != null) {
System.out.printf("%d%c",currentNode.data, currentNode.next == null ? '\n' : ' ');
currentNode = currentNode.next;
}
}
}
public class Main {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNextInt()) {
int n = sc.nextInt();// 接收输入的链表长度
LinkList linkList = new LinkList();// 构建一个新链表
for (int i = 0; i < n; i++) {
linkList.insert(sc.nextInt());// 输入的数据插到链表中
}
linkList.printLinkList();// 打印链表节点
}
sc.close();
}
}