1.特点
通过指针连接起来的结点存储数据元素;
2. 节点结构由数据域和指针域组成
3.分类
3.1 单链表
说明,头部指向第一个元素的地址,第一个元素指针域指向第二个元素,依次指向,最后一个元素指针域为空,没有指向其它元素,这样的节点通过指针域构成起来的链表称为单链表
3.2 循环链表
最后一个元素的指针域指向头部构成一个元素链表
扫描二维码关注公众号,回复:
5721256 查看本文章
3.3 双链表
有两个指针域,记住前一个元素的地址和后一个元素的地址,可以从双向遍历元素,相比于单链表遍历方式增加灵活性,但是占用多一个指针域空间
4.单链表插入和删除示意图
4.1 在单链表中插入结点
插入新元素c,把a元素的指针域指向c元素,把c元素的指针指向b元素
4.2 单链表中删除元素
删除b元素,a元素指向b元素的指针改成指向c元素
5.Java语言实现链式
5.1 说明:定义一个静态内部类Node,称为结点,结点与结点相连在一起构成链式数据结构,每个结点有两个数据域,一个指向数据,另一个指向另外一个结点
5.2 在包中定义一个静态内部类
/**
* 定义一个嵌套类,嵌套类与内部类的区别在于嵌套类是静态,内部类不是静态
* @param <E>
*/
private static class Node<E> {
/**
* 指向对象一个引用,结点的数据部分
*/
E data;
/**
* 指向下一个结点引用
*/
Node next;
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
5.3 外部类添加方法
/**
* 添加元素方法
* @param e
* @return
*/
public boolean add(E e){
//创建一个新结点,数据域保持数据对象
Node<E> newNode = new Node<>(e);
//记下前面一个结点地址
newNode.next = first;
//把当前结点赋给头结点
first = newNode;
size ++;
return true;
}
测试效果如下:
封装的数据格式如下:
6.简单代码示意
public class CustomLinkedList<E> {
/**
* 头引用,指向第一个元素
*/
private Node first;
/**
* 记录元素的个数
*/
private int size;
/**
* 添加元素方法
* @param e
* @return
*/
public boolean add(E e){
//创建一个新结点,数据域保持数据对象
Node<E> newNode = new Node<>(e);
//记下前面一个结点地址
newNode.next = first;
//把当前结点赋给头结点
first = newNode;
size ++;
return true;
}
public Object[] toArray(){
Object[] result = new Object[size];
int i = 0;
for(Node<E> e = first;e != null; e = e.next){
result[i++] = e.data;
}
return result;
}
/**
* 判断结点链中数据域是否等于给定的值
* @param e
* @return
*/
public boolean contains(E e){
if(e == null){
return false;
}
boolean found = false;
Node<E> currentNode = first;
while(!found && currentNode != null){
if(e.equals(currentNode.data)){
found = true;
}else {
currentNode = currentNode.next;
}
}
return found;
}
/**
* 基本思路是删除一个结点,并将头引入指向第二结点
* @return
*/
public E remove(){
E result = null;
if(first != null){
//读取头结点数据域
result = (E)first.data;
//将头结点指向第二个结点
first = first.next;
size --;
}
return result;
}
/**
* 1.用链中的第一个结点数据域替换要移除值所在的结点
* 2.从链中删除第一个结点
* @param e
* @return
*/
public boolean remove(E e){
boolean result = false;
Node<E> currentElementNode = getReferenceNode(e);
if( currentElementNode != null){
//当前结点数据域保持第一个结点数据域
currentElementNode.data = (E)first.data;
//移除第一个结点
first = first.next;
size --;
result = true;
}
return result;
}
/**
* 清空链表
*/
public void clear(){
while (!isEmpty()){
remove();
}
}
/**
* 判断是否为空
* @return
*/
public boolean isEmpty(){
return size == 0;
}
/**
* 根据给定的元素,获取该元素在链中的结点引用
* @param e
* @return
*/
private Node<E> getReferenceNode(E e){
boolean found = false;
Node<E> currentNode = first;
while (!found && currentNode != null){
if(e.equals(currentNode.data)){
found = true;
}else {
currentNode = currentNode.next;
}
}
return currentNode;
}
/**
* 定义一个嵌套类,嵌套类与内部类的区别在于嵌套类是静态,内部类不是静态
* @param <E>
*/
private static class Node<E> {
/**
* 指向对象一个引用,结点的数据部分
*/
E data;
/**
* 指向下一个结点引用
*/
Node next;
public Node(E data) {
this.data = data;
}
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
}