02.单链表-史上最清晰的尾插法和头插法
1.单链表
- 链表是一系列的存储数据元素的单元,通过指针(引用)串联起来的,因此每个单元至少有两个域,一个域用于数据元素的存储,另一个域是指向其他单元的指针。
- 单链表是链表的其中一种基本结构。一个最简单的结点结构如图所示,它是构成单链表的基本结点结构。
- 在结点中数据域用来存储数据元素,指针域用于指向下一个具有相同结构的结点。
2.链表定义
- 链表可增加任意类型数据元素,将其类LinkList定义为泛型。
- 定义头指针head、及链表长度size。
- 定义内部类Node,同样为泛型。
- 定义泛型对象E element
- 节点类Node next
public class LinkList<E> {
Node head = null ;
public int size = 0;
//定义内部类Node(存在泛型E和节点Node)
private class Node<E>{
E element;
Node next;
public Node(E element, Node next) {
this.element = element;
this.next = next;
}
}
}
3.链表长度
public int size(){
return size;
}
4.头插法
4.1头插法:把后建立的结点插在头部。用这种方法建立起来的链表的实际顺序与输入顺序刚好向反,输出时为倒序!
- 图解:
- 说明
- 第1步,把新节点的next指针指向原先的头结点:Node node = new Node<>(element,head);
- 第2步,把新节点变为链表的头结点: head = node;
- 最后size自增。
public void addFirst(E element){
Node node = new Node<>(element,head);
head = node;
size++;
}
5.尾插法
- 图解
-
说明
把最后一个节点的next指针指向新插入的节点即可。
- 注意点:
- 需要判断链表首次插入是否为空,
- 依次从头遍历链表,循环条件:0到size-1,取得最后一个节点。
- 通过new Node(element,proNode.next)将新创建的节点指向最后一个节点。
- 最后在将最后节点的指针指向新节点、即可。
- 注意点:
public void addTail(E element){
if (head == null){
Node node = new Node<>(element , head);
head = node;
size++;
}else{
Node preNode = head;
for (int i = 0 ; i < size - 1 ; i++){
preNode = preNode.next;
}
preNode.next = new Node(element,preNode.next);
size++;
}
}
6.重写toString方法
public String toString(){
StringBuilder str = new StringBuilder();
Node node = head;
str.append("size: ").append(size);
str.append(" link: [");
while(node != null){
str.append(node.element);
if (node != null){
str.append("--->");
}
node = node.next;
}
str.append("]");
return str.toString();
}
7.完整代码实现
- 方法类
package demo.linkdemo;
public class LinkList<E> {
Node head = null ;
public int size = 0;
//定义内部类Node(存在泛型E和节点Node)
private class Node<E>{
E element;
Node next;
public Node(E element, Node next) {
this.element = element;
this.next = next;
}
}
/**
* 求链表长度
* @return
*/
public int size(){
return size;
}
public void clean(){
head = null;
size = 0;
}
/**
* 头插法
* @param element
*/
public void addFirst(E element){
Node node = new Node<>(element,head);
head = node;
size++;
}
/**
* 尾插法
* @param element
*/
public void addTail(E element){
if (head == null){
Node node = new Node<>(element , head);
head = node;
size++;
}else{
Node preNode = head;
for (int i = 0 ; i < size - 1 ; i++){
preNode = preNode.next;
}
preNode.next = new Node(element,preNode.next);
size++;
}
}
/**
* 打印集合
* @return
*/
public String toString(){
StringBuilder str = new StringBuilder();
Node node = head;
str.append("size: ").append(size);
str.append(" link: [");
for (int i = 0 ; i < size ; i++){
str.append(node.element);
if (node.next != null){
str.append("--->");
}
node = node.next;
}
str.append("]");
return str.toString();
}
}
- 测试类
package demo.linkdemo;
public class LinkListTest {
public static void main(String[] args) {
LinkList list = new LinkList();
System.out.println("-------------头插法---------------");
list.addFirst("001");
list.addFirst("002");
list.addFirst("003");
list.addFirst("004");
list.addFirst("005");
System.out.println(list);
list.clean();
System.out.println("-------------尾插法---------------");
list.addTail("001");
list.addTail("002");
list.addTail("003");
list.addTail("004");
list.addTail("005");
System.out.println(list);
}
}