在这里主要写的是单向链表和双向链表的内存结构分析,在java中为我们提供了LinkedList实现类用于链表的使用
一、链表
1.什么是链表
链表 [Linked List]:链表是由一组不必相连【不必相连:可以连续也可以不连续】的内存结构 【节点】,按特定的顺序链接在一起的抽象数据类型。
2.链表的分类
链表分为单向链表(Singly linked lis)、双向链表(Doubly linked list)、循环链表(Circular Linked list)。
3.链表的优缺点
优点:随机增删元素的效率增高,(因为增删元素不涉及大量元素位移)
缺点:查询效率较低,每一次查找元素都需要从头节点开始往下遍历
二、单向链表
1.内存结构
2.用java实现单向链表(增删改查功能实现)
链表的基本单元是节点Node,节点有两个属性:第一个储存数据,第二个储存下一节点的内存地址
public class Node {
Object data;
Node next;
public Node() { }
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", next=" + next +
'}';
}
}
单向链表,第一个节点为头节点,通过节点实现增删改查功能
public class Link {
//头节点
Node header = null;
int size = 0;
public int size() {
return size;
}
//增
public void add(Object data) {
if (header == null) {
header = new Node(data, null);
} else {
Node currentlastNode = findLast(header);
currentlastNode.next = new Node(data, null);
}
size++;
}
//找到链表的最后一个节点
private Node findLast(Node node) {
if (node.next == null) {
return node;
}
return findLast(node.next);
}
//删
public void remove(Object data) {
Node temp = header;
boolean flag = false;
while (true) {
if (temp.data == data) {
flag = true;
break;
}
temp = header.next;
}
if (flag) {
temp.next = temp.next.next;
}else {
System.out.println("没有找到此节点");
}
size--;
}
//改
public void update(Object obj, Object newobj) {
Node temp = header;
boolean flag = false;
while (true) {
if (temp.data == obj) {
flag = true;
break;
}
temp = header.next;
}
if (flag) {
temp.data = newobj;
}else {
System.out.println("没有找到此节点");
}
}
//查
public Object select(Object o) {
Node temp = header;
boolean flag = false;
while (true) {
if (temp.data == o) {
flag = true;
break;
}
temp = header.next;
}
if (flag) {
System.out.println("你所查的数据为" + temp.data);
}
return size;
}
}
测试类:
public class LinkText {
public static void main(String[] args) {
Link link = new Link();
link.add("11");
link.add(11111111);
link.add("abc");
link.remove("11");
int size1 = link.size();
System.out.println(size1);
link.update("abc","qqq");
Object qqq = link.select("qqq");
System.out.println(qqq);
System.out.println(link.header);
}
}
运行结果:
2
你所查的数据为qqq
2
Node{data=11, next=Node{data=qqq, next=null}}
三、双向链表 (LinkedList实现类)
双向链表的节点Node具有三个属性:第一个为上一个节点的内存地址,第二个为数据,第三个为下一个节点的内存地址。
内存图:
通过看LinkedList底层源代码我们可以看出,底层底层用了first和last进行头节点和尾节点的内存地址存储
LinkedList底层没有初始化,first和last的引用初始都是Null
因为LinkedList实现了Collection接口,所以这里方法就不多说了。
代码展示:
public class LinkLastText {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(111);
linkedList.add("1");
//双向链表,对于链表数据结构来说随机增删效率较高,检索效率低,内存地址不连续
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
}