是否还在为java单链表操作而烦恼呢,来康康这两天现学现编的java单链表基本操作,程序里的注释我觉得写的很清楚撩,小伙伴们结合学到的链表知识和java关于对象和类那部分的知识应该可以看懂。这篇文章是来自一个java初学者的纯自编货,历时8小时(没学过数据结构加上c语言忘的差不多真的伤不起)编出来的纯纯干货,阔以康康。
实验内容及目的
1.实验内容
面向对象实验要求
- 设计Node类,有2个成员
- 成员private int value;
- 成员 private Node next;
- 公有构造方法public Node(int value);给成员value赋值
- 成员value和next的getter/setter方法
- 设计MyList类,实现有序(升序)链表功能,链表的节点用Node的实例表示
public class MyList{
private int size;//链表节点数量
private Node head;//成员指向链表的第一个节点
//构造方法初始化一个空链表
public MyList();
//获取链表的节点数
public getSize();
//获取第一个节点
public Node getHead();
//在链表中根据Node的value值把节点插入适合的位置
public void insertNode(Node node);
//根据给定的值,返回链表中的节点对象,如不存在节点则返回null值,如存在多个相 //同的值, 返回第一个检索到的节点
public Node getNode(int value);
//根据给定的值,删除链表中的节点对象
public boolean removeNode(int value);
}
3.编写TestMyList类,在main方法里测试以上两个类的各个方法
- 实验目的
(1)通过构建类提高程序的灵活性和更多的模块化,体现模块化编程的优势
(2)熟练运用链表,编程实现链表元素初始化,添加,排序,删除,查找等功能
- 实验原理及基本技术路线图(方框原理图)
本次上机主要是运用java面向对象的编程思想,编写Node类和MyList类,根据需要调用类中不同方法或数据域,实现链表基本操作。链表的检索、删除、插入、排序等操作的基础操作就是链表遍历,即从头节点head遍历整个链表直到节点指针域为null(最后一个节点的指针域就为null)。遍历实际上就是节点指针域的移动访问,这里需要构建临时节点temp来暂时储存相邻节点,方便下步对节点数据域的访问和修改。还有就是节点指针域的访问经常容易出现指针域访问出错的问题,因为指针域若在未指明指向的时候默认为null,且程序中各类的数据域都做了封装。需要通过getter访问器和setter修改器对节点进行操作,所以在理清节点间关系时还要注意访问和修改节点时指针域的指向问题。
- 所用仪器、材料(设备名称、型号、规格等)
1 台 PC 及 eclipe软件
- 实验方法、步骤(程序代码或操作过程)
程序源代码
Node类impo
import java.util.Scanner;
public class Node {
private int value;//数据域
private Node next;//指针域
//Construct a node with a specified value
public Node(int value) {
this.value = value;
this.next = null;
}
public Node() {
this(0);
}
//Return value
public int getValue() {
return value;
}
//Return next
public Node getNext() {
return next;
}
//Set a new value
public void setValue(int value) {
this.value = value;
}
//Set a new next
public void setNext(Node next) {
this.next = next;
}
//Print list
public static void printList(Node node) {
System.out.print("List:head-->");
while(node != null) {
System.out.print(node.getValue() + "-->");
node = node.getNext();
if(node == null)
System.out.print("end");
}
System.out.println();
}
//Construct a new node
public static Node constructNewNode() {
System.out.print("Enter the value of the node: ");
Scanner input = new Scanner(System.in);
Node node = new Node(input.nextInt());
return node;
}
Mylist类
import java.util.Scanner;
public class MyList {
private static int size;//链表节点数量,因为要该类多个方法要使用该值所以定义为静态
private Node head;//成员指向链表的第一个节点,头指针
Scanner input = new Scanner(System.in);
//构造方法初始化一个空链表
public MyList() {
this.size = 0;
this.head = new Node(0);
}
//获取链表的节点数
public int getSize() {
return this.size;
}
//获取第一个节点
public Node getHead() {
return head.getNext();
}
//在链表中根据Node的value值把节点插入适合的位置
public void insertNode(Node node) {
if(size == 0) {
head.setNext(node);
}
else {
Node temp = new Node(0);
temp.setNext(head.getNext());//原来头指针指向的节点地址存入临时节点temp
//如果该节点的值小于原头指针指向那个节点的值
if(node.getValue() <= (head.getNext()).getValue()) {
node.setNext(head.getNext());//将原头指针指向的节点接在该节点后
head.setNext(node);//头指针指向该节点
}
else {
//顺序检索链表
while(temp != null) {
//如果待插入值大于前节点值且小于后节点值
if(node.getValue() > temp.getValue() &&
node.getValue() <= (temp.getNext()).getValue()) {
node.setNext(temp.getNext());//将待添加节点接到后一节点
temp.setNext(node);//将前一节点接到待添加节点上
break;
}
temp = temp.getNext();
if(temp.getNext() == null){//当检索到最后一个节点
node.setNext(temp.getNext());
temp.setNext(node);
break;//因为改变了最后一个节点指针值,所以必须加break跳出循环,不然会无限循环
}
}
}
}
this.size++;//链表元素计数加一
}
//根据给定的值,返回链表中的节点对象,如不存在节点则返回null值,如存在多个相同的值,返回第一个检索到的节点
public Node getNode(int value) {
Node temp = new Node(0);
temp.setNext(head);
//顺序检索链表
while(temp != null) {
//当检索到给定值时跳出循环,即使有多个相同的特定值第一个特定值出现后便不再检索
if(value == temp.getValue()) {
break;
}
temp = temp.getNext();
}
return temp;//返回检索到的特定值所在节点位置,若未检索到特定值则temp为null
}
//根据给定的值,删除链表中的节点对象
public boolean removeNode(int value) {
Node temp = new Node();
Node pretemp = new Node();//定义一个节点,用来存储查找到特定值节点前一个节点
temp.setNext(head);
//顺序检索链表
while(temp != null) {
//当检索到给定值时跳出循环,即使有多个相同的特定值第一个特定值出现后便不再检索
if(value == temp.getValue()) {
System.out.print(temp.getValue());
break;
}
pretemp = temp;//存储下此次循环指针移动之前的节点
temp = temp.getNext();//指针移动
}
if(temp == null) {//如果给定值不再链表内
return false;
}
else {//给定值在链表内
pretemp.setNext(temp.getNext());//将待删除节点的下一个节点接到待删除节点前一节点
size--;
return true;
}
}
}
TestMylist类
import java.util.Scanner;
public class TestMylist {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
MyList list = new MyList();
Node node1 = Node.constructNewNode();
list.insertNode(node1);
Node node2 = Node.constructNewNode();
list.insertNode(node2);
Node node3 = Node.constructNewNode();
list.insertNode(node3);
Node node4 = Node.constructNewNode();
list.insertNode(node4);
System.out.println("The number of nodes is: " + list.getSize());//获取链表节点个数
Node.printList(list.getHead());//打印链表
//输入给定值,返回链表中的节点对象,如不存在节点则返回null值,如存在多个相同的值,返回第一个检索到的节点
System.out.print("Enter the value you want to find:");
Node find = list.getNode(input.nextInt());
if(find == node1)
System.out.println("The node you find is: node1");
else if(find == node2)
System.out.println("The node you find is: node2");
else if(find == node3)
System.out.println("The node you find is: node3");
else if(find == node4)
System.out.println("The node you find is: node4");
else
System.out.println("The node you find is not in the list");
//删除用户想要删除的的节点
System.out.print("Enter the value you want to delete:");
boolean isDelete = list.removeNode(input.nextInt());
if(isDelete == false) {
System.out.print("This node is not in the list.");
}
else {
System.out.println("The new list:");
Node.printList(list.getHead());//输出删除过后的链表
System.out.println("The number of nodes is: " + list.getSize());//删除节点后的链表节点数
}
}
}
- 实验过程原始记录(数据、图表、计算等)
程序运行结果截图
- 实验结果、分析和结论(误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸)
- 本次上机主要是对前期学习的基本程序设计技术的提高一个层次的运用,通过使用类的整合,在编程过程中根据需要调用相应类的相应方法或数据域达到程序要求。类的构建可以提高程序的灵活性和更多的模块化,增强程序的可读性,减少大量的重复代码,对后期更加复杂程序的编写提供了面向对象的编程思想。
2.因为没有学过数据结构,开始时对链表的结构和怎样运用编程实现链表操作还有一定困难,特别在头节点、头指针的概念还有混淆,后期通过问老师和查找资料现在认识比较清晰,链表简单来说就是通过指针域链接的数据链,重点在于指针域的操作。
3.本次编程最主要的就是对链表节点数据域和指针域的访问及修改,加上数据封装,把数据域都设计为私有,编写过程中也很多次出现因为指针域访问问题,在未指明指针域的指向前,Node类型的引用都默认为null,这就会导致指针域不能直接从null修改为指向其他节点。
4.还有一个重要的单链表操作就是链表的遍历,即从头节点开始检索通过指针域链接的链表,直到指针域指向null(最后一个节点的指向为null),不论是检索,删除,添加,排序等操作,对链表的遍历是基础操作。