单向链表
必备知识
什么是内部类
java内部类分为静态内部类,实例内部类,匿名内部类,局部内部类,本次开发采用实例内部类。其余的内部类将在以后的文章中详细说明
内部类的简单使用
新建空工程
结构如下
实例内部类的简单使用
public class MyList {
public class Node{
public void test(){
System.out.println("This is test");
}
}
}
测试实例内部类
public class MyTest {
@Test
void testList(){
Node node = new MyList().new Node();
node.test();
}
}
结果展示
链表开发
基本思想
对于单向链表,外部类需要有size,以及一个指针向链表的头
修改MyList
大体结构
public class MyList {
long size;//链表大小
Node firstNode;//第一个节点
public class Node{
private int value;//每个节点的类型
private Node preNode;//当前节点的上一个节点
private Node nextNode;//当前节点的下一个节点
private Node() {
//私有化无参构造器
}
public Node(int value)
{
//构造器赋值
this.value = value;
}
//get*使用public,也可以在测试代码中使用
//set*使用private,只在外部类中使用
public int getValue() {
return value;
}
private void setValue(int value) {
this.value = value;
}
public Node getPreNode() {
return preNode;
}
private void setPreNode(Node preNode) {
this.preNode = preNode;
}
public Node getNextNode() {
return nextNode;
}
private void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
/*@Override
//千万不要写成这种形式,会造成栈溢出问题
public String toString() {
return "Node [value=" + value + ", preNode=" + preNode + ", nextNode=" + nextNode + "]";
}*/
@Override
public String toString() {
return "Node [value=" + value + "]";
}
}
public Node getFirstNode() {
return firstNode;
}
public void setFirstNode(Node firstNode) {
//只在大小为0是可以使用
if(this.size ==0)
{
this.firstNode = firstNode;
this.size++;
}
else return;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public void addNode(Node node)
{
//分情况
if(this.size == 0)
{
//TODO
}
else {
//TODO
}
this.size++;
}
public void deleteNode(Node node)
{
if(this.size == 0)
{
return;
}
else
{
//TODO
this.size--;
}
}
@Override
public String toString() {
return "MyList [size=" + size + ", firstNode=" + firstNode + "]";
}
}
增加
MyList的完善
首先对于setFirstNode的完善
public void setFirstNode(Node firstNode) {
if(this.size ==0)
{
//如果本身没有节点,那么设置第一个节点就是添加第一个节点
this.firstNode = firstNode;
this.firstNode.setNextNode(null);
this.firstNode.setPreNode(null);
this.size++;
}
else
{
//如果本身有数量,则仅仅是替换第一个节点
Node preNode = this.firstNode.getPreNode();
Node nextNode = this.firstNode.getNextNode();
this.firstNode = firstNode;
this.firstNode.setPreNode(preNode);
this.firstNode.setNextNode(nextNode);
}
}
接下来我们完善addNode方法,这样我们就可以进行测试了
public void addNode(Node node)
{
if(this.size == 0)
{
//如果没有节点,直接赋值,数量+1,无需进行其余操作
this.firstNode = node;
this.firstNode.setNextNode(null);
this.firstNode.setPreNode(null);
}
else {
//如果有节点,首先找到最后的节点,然后赋值,数量+1
Node currNode = this.firstNode;
while(currNode.getNextNode() != null)
{
currNode = currNode.getNextNode();
}
node.setPreNode(currNode);
currNode.setNextNode(node);
node.setNextNode(null);
}
this.size++;
}
添加测试
测试1:测试没有节点时的setFirstNode
@Test
void testsetFirstNode(){
Node node1 = new MyList().new Node(1);
MyList myList = new MyList();
myList.setFirstNode(node1);
System.out.println(myList.getFirstNode());
System.out.println(myList.getSize());
}
结果展示
测试2:测试有节点时的setFirstNode
@Test
void testsetFirstNode2(){
Node node1 = new MyList().new Node(1);
Node node2 = new MyList().new Node(2);
MyList myList = new MyList();
myList.setFirstNode(node2);
System.out.println("---原来的链表----");
System.out.println(myList.getFirstNode());
System.out.println(myList.getSize());
System.out.println("---更改后的链表----");
myList.setFirstNode(node1);
System.out.println(myList.getFirstNode());
System.out.println(myList.getSize());
}
结果展示
测试3:没有节点时,使用addNode
@Test
void testaddNode(){
Node node1 = new MyList().new Node(1);
MyList myList = new MyList();
myList.addNode(node1);
System.out.println(myList.getFirstNode());
System.out.println(myList.getSize());
System.out.println(myList);
}
结果展示
测试4:有节点时,使用addNode
@Test
void testaddNode1(){
Node node1 = new MyList().new Node(1);
Node node2 = new MyList().new Node(2);
MyList myList = new MyList();
myList.addNode(node1);
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("-------添加节点后-----");
myList.addNode(node2);
System.out.println("第一个节点:"+myList.getFirstNode());
System.out.println("添加的节点:"+node2);
System.out.println("第一个节点的后继节点"+myList.getFirstNode().getNextNode());
System.out.println("添加节点的前驱节点"+node2.getPreNode());
System.out.println("链表大小"+myList.getSize());
}
结果展示
测试5:用setFirstNode添加第一个节点,addNode添加别的
@Test
void testaddNode2(){
Node node1 = new MyList().new Node(1);
Node node2 = new MyList().new Node(2);
MyList myList = new MyList();
myList.setFirstNode(node1);
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("-------添加节点后-----");
myList.addNode(node2);
System.out.println("第一个节点:"+myList.getFirstNode());
System.out.println("添加的节点:"+node2);
System.out.println("第一个节点的后继节点"+myList.getFirstNode().getNextNode());
System.out.println("添加节点的前驱节点"+node2.getPreNode());
System.out.println("链表大小"+myList.getSize());
}
展示
测试6:用add添加第一个节点,setFirstNode添加别的
@Test
void testaddNode3(){
Node node1 = new MyList().new Node(1);
Node node2 = new MyList().new Node(2);
MyList myList = new MyList();
myList.addNode(node1);
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("-------替换第一个节点后-----");
myList.setFirstNode(node2);
System.out.println("替换的节点:"+node2);
System.out.println(myList);
System.out.println("链表大小"+myList.getSize());
}
展示
删除
MyList的完善
对于链表来说,适合删除以及添加操作,不适合修改,以及查询操作,所以对于按值删除某一节点同样不适合,这里先修改为删除第一个节点以及最后一个节点,按值删除,后续追加
public void deleteFirstNode()
{
if(this.size == 0)
{
return;
}
else if(this.size ==1 )
{
this.firstNode = null;
}
else {
this.firstNode = this.firstNode.getNextNode();
}
this.size--;
}
public void deleteLastNode()
{
if(this.size == 0)
{
return;
}
else if(this.size ==1 )
{
this.firstNode = null;
}
else {
Node currNode = this.firstNode;
while(currNode.getNextNode() != null) currNode = currNode.getNextNode();
Node preNode = currNode.getPreNode() ;
preNode.setNextNode(null);
}
this.size--;
}
删除测试
测试1:没有元素,删除第一个元素
@Test
void testdeleteNode(){
MyList myList = new MyList();
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("------删除第一个元素--------");
myList.deleteFirstNode();
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
}
展示
测试2:有元素,删除第一个元素
@Test
void testdeleteNode2(){
MyList myList = new MyList();
Node node1 = new MyList().new Node(1);
myList.addNode(node1);
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("------删除第一个元素--------");
myList.deleteFirstNode();
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
}
展示
测试3:没有元素,删除最后一个元素
@Test
void testdeleteNode3(){
MyList myList = new MyList();
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("------删除最后一个元素--------");
myList.deleteLastNode();
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
}
展示
测试4:有元素,删除最后一个元素
@Test
void testdeleteNode4(){
MyList myList = new MyList();
Node node1 = new MyList().new Node(1);
Node node2 = new MyList().new Node(1);
myList.addNode(node1);
myList.addNode(node2);
System.out.println("------原链表--------");
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
System.out.println("------删除第一个元素--------");
myList.deleteLastNode();
System.out.println("第一个节点"+myList.getFirstNode());
System.out.println("链表大小"+myList.getSize());
System.out.println(myList);
}
展示