一.链表的概念
定义:链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构。
特点:链表由一系列节点(链表中每一个元素称为节点)组成,节点在运行时动态生成 (malloc),每个节点包括两个部分:① 一个是存储数据元素的数据域 ② 另一个是存储下一个节点地址的指针域。简单的说 链表一部分是数存储数据的 一部分是存储下一个节点的地址的
链表的构成(初始化)
public class Node<E>{
//该节点的数据
E val;
//下一个节点
Node<E> next;
//构造器
Node<E>(E x){
val = x;
next = null;
}
}
链表节点分为两个域
数据域:存放各种实际的数据,如:num、score等
指针域:存放下一节点的首地址,如:next等.
链表的操作(增删改查)
①链表的遍历:
/*
*实现思路:由于链表其实就是把他看做 一圈小朋友进行手拉手进行游戏
*我们只需要判断他的下一个是否有签这下一个小朋友的手 就可以进对链表进行遍历操作
*/
public static int getListNode(Node node){
int length = 0;
while(node!= null){
node = node.next;
//TODO:可以在这边把链表的每个节点打印出来
length++;
}
return length;
}
②链表的插入:
示意图:
/*
*链表的插入 ①头部插入:我们只要链表的投节点是不存在节点的 因此我们把需要插入的节点
*的指针域指向投节点的地址即可
public class myLinkedList<E>{
private final Node<E> head, tail;
private int size;
// 单链表链表节点
private static class Node<E> {
E val;
Node<E> next;
Node(E val) {
this.val = val;
}
}
// 构造函数初始化头尾节点
public MyLinkedList2() {
//其实这两个节点可以看成两个 哨兵节点(虚拟的节点)
this.head = new Node<>(null);
this.tail = new Node<>(null);
head.next = tail;
this.size = 0;
}
public void addFirst(E e){
Node<E> newNode = new Node(e);
Node<E> temp = new Node();
newNode.next = temp;
head.next = newNode;
size++;
}
}
可以看出上面的代码 进行初始化了 private final Node<E> head, tail; private int size;
对于节点head 和 tail 为了我们对边界的控制 我们所设立的哨兵节点 他是 head永远是头节点,tail永远是最末尾的节点。
③链表的删除:
(1)删除头节点
(2)删除尾节点
(3)删除指定位置节点
/**
* 删除头节点 就是把该节点置为null
* @return 节点数据
*/
public E removeFirst() {
//先原本的头节点找出
Node<E> x = head.next;
//只需要将我们的哨兵节点指向 下下一个节点即可
head.next = head.next.next;
x = null;
size--;
return x.val;
}
/**
* 删除尾节点
* @return 节点信息
*/
public E removeLast() {
//原本的尾节点
Node<E> x = getNode(size-1);
Node<E> temp ;
if(size-2>0){
//最后一个节点的上一个节点
temp = getNode(size-2);
}else {
temp = head;
}
temp.next = tail;
//将原本的node 的指针域变为null
x.next = null;
return x.val;
}
/**
* 删除对应index 的节点
* @param index 索引
* @return 节点信息
*/
public E remove(int index) {
Node<E> node = getNode(index);
Node<E> perv;
if(size-1>0){
perv = getNode(index-1);
}else {
perv = head;
}
perv.next = node.next;
node.next = null;
return perv.val;
}
④获取链表信息:
/**
* 获取头节点
* @return 信息
*/
public E getFirst() {
return head.next.val;
}
public E getLast() {
//获取到尾节点
return getNode(size - 1).val;
}
/**
* 获取指定节点
* @param index 索引
* @return 信息
*/
public E get(int index) {
return getNode(index).val;
}
⑤修改链表信息:
/***** 改 *****/
public E set(int index, E element) {
checkElementIndex(index);
Node<E> p = getNode(index);
E oldVal = p.val;
p.val = element;
return oldVal;
}