自己动手写一个简单的单向链表结构
链表结构,是一个相对比较复杂的结构,不过也不难理解。尤其是我们在学习了Java中的数据类型之后,了解了除了基本的数据类型,其他的数据类型都是引用数据类型,也就是说,引用了它们的地址值。
关于链表结构,它的特点是插入删除特别的方便,但是查询就会比较麻烦,因为单向链表只在头结点保存了对下一个结点的引用,如果你要查询链表中某个元素的数据,那么就得从头结点开始遍历整个链表,可以说是相当慢了。但是插入元素结点是很方便的,只需要将要查如位置的前一个元素结点的指针域指向要插入元素结点,再把要查如元素结点的指针域指向要插入位置的下一个结点,这样,结点就被插进去了。
但是在本案例中的单向链表,最高效的是头插法,因为从中间部位插入,还是要遍历一部分链表,下图是单向链表的头插法示意图。
自己动手写一个链表结构,首先是数据结点:
package myLinkList;
public class Node {
// 数据域
public long data;
// 指针域
public Node next;
/**
* 默认构造方法装入元素数据
* @param value
*/
public Node(long value) {
this.data = value;
}
/**
* 显示方法,打印本结点中的数据
*/
public void show() {
System.out.print(data + " ");
}
}
接着是链表的主体,就是将一个个结点连接起来的部分:
package myLinkList;
public class LinkList {
// 定义一个头结点
private Node first;
// 头结点初始为null
public LinkList() {
first = null;
}
/**
* 从头部结点插入,又称为头插法,指针域部分主要是地址引用的原理
* @param value
*/
public void insertFirst(long value) {
// new出新的数据结点
Node node = new Node(value);
// 新的结点引用原来的头结点
node.next = first;
// 插入之后,新的结点变成了头结点
first = node;
}
/**
* 删除结点,将头结点的引用的结点变为头结点
*/
public void deleteFirst() {
first = first.next;
}
/**
* 遍历整个链表,打印出所有结点的数据
*/
public void showall() {
// 首先,获取头结点为当前的结点
Node currentNode = first;
// 开始遍历,当当前结点不为null时,打印
while (currentNode != null) {
currentNode.show();
// 步进,当前结点引用的下一个结点为当前结点,循环
currentNode = currentNode.next;
}
}
/**
* 查询数据结点,返回结点
* @param value
* @return
*/
public Node search(long value) {
// 依然是遍历,方法一样的
Node currentNode = first;
while(currentNode.data != value) {
if(currentNode.next == null) {
// 如果查到最后了还没有查到,则返回null,表明没有找到数据
return null;
}
currentNode = currentNode.next;
}
// 如果找到了匹配的数据,则退出循环,返回当前的结点
return currentNode;
}
/**
* 删除指定的结点
* @param value
* @return
*/
public Node deleteNode(long value) {
// 当前结点
Node currentNode = first;
// 前一个结点
Node previousNode = first;
// 开始循环遍历
while(currentNode.data != value) {
// 如果找到最后了依然没有匹配数据,则返回null,啥也不干
if(currentNode.next == null) {
return null;
}
// 循环步进,就是往后移动
previousNode = currentNode;
currentNode = currentNode.next;
}
// 如果第一个结点就匹配了,则跟从头部删除一样,直接调用
if(currentNode == first) {
this.deleteFirst();
}else {
// 如果不是头部匹配的数据,则直接让上一个数据结点的引用指向当前结点的下一个结点
previousNode.next = currentNode.next;
}
// 返回这个结点
return currentNode;
}
}
测试代码:
package myLinkList;
public class TestLinkList {
public static void main(String[] args) {
LinkList list = new LinkList();
list.insertFirst(23);
list.insertFirst(12);
list.insertFirst(2);
list.insertFirst(26);
list.insertFirst(98);
/*
* System.out.println(); list.showall(); System.out.println(); Node node =
* list.search(26); node.show();
*/
list.showall();
Node delNode = list.deleteNode(26);
System.out.println();
System.out.println("删除的数据为"+delNode.data);
list.showall();
list.deleteFirst();
System.out.println();
list.showall();
}
}
控制台输出结果:
98 26 2 12 23
删除的数据为26
98 2 12 23
2 12 23