单链表
是一种链式存取的数据结构,是用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,而结点是由数据域
(存储数据元素)和 指针域(也称链域,存储下一个结点的地址)构成的。- 链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,每个结点只有一个链域的链表称为单链表(Single Linked
List)。
Java实现链表
定义一个结点类:
package com.ashley.linkedlist;
public class Node {
private Object data;//数据域
private Node next;//指针域,由于指针指向的是一个结点,所以定义为Node型
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
创建单链表:
Node head = null;//定义头结点
Node tail = null;//定义尾结点
Node tmpNode = null;//定义临时结点
for (int i = 0; i < 10; i++) {
Node node = new Node();//添加结点
node.setData(i);//存入数据
head = node;//将新建的结点设置为头结点
if (i == 0) {
tail = node;//判断,将角标为0的结点设置为尾结点
}
node.setNext(tmpNode);//设置指针指向临时结点
tmpNode = node;//将新建的结点设置为临时结点(第一趟结束,node0 = 0,且尾结点为node0,指针指向它)
}
//循环结束,链表为:9——>8——>7——>6——>5——>4——>3——>2——>1——>0
查找指定数据的节点:
tmpNode = head;//for循环每结束一次,就将头结点设置为临时结点
int target = 6;//指定查找的目标数据
while(tmpNode != null) {//当临时结点不为空,执行以下操作
if ((int)tmpNode.getData() == target) {//当临时结点的数据和查找的目标一致,就打印出来,并结束操作
System.out.println(tmpNode.getData());//6
break;
}
tmpNode = tmpNode.getNext();//不符合就看下一个结点
}
查找指定结点的数据:
int n = 7;//指定查找的目标结点
tmpNode = head;
int i = 0;//定义遍历的当前位置
while(tmpNode != null) {
i++;
if (i == n) {
System.out.println(tmpNode.getData());//3
break;
}
tmpNode = tmpNode.getNext();
}
打印单链表的长度:
tmpNode = head;
int length = 0;//初始化长度
while(tmpNode != null) {
length++;//第一趟结束length为1
tmpNode = tmpNode.getNext();
}
System.out.println(length);//10
数组和单链表的比较:
(1)数组逻辑相邻,物理也相邻;单链表逻辑相邻,物理不一定相邻。
(2)数组根据下标取值,必须分配连续的内存;单链表不需要分配连续的内存
(3)数组的空间通常是有限的(取决于连续空间);单链表的的空间是无限的(物理内存范围内)。
(4)数组插入,删除元素效率低,需要移动大量元素,但是查找效率高(查找一个元素的时间复杂度为O(1);单链表是离散存储的,插入、删除效率高,只需改变指针指向的结点,查找效率低(查找一个元素的时间复杂度为O(n))。
查找测试:
package com.ashley.linkedlist;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList();//定义一个数组
List<Integer> list2 = new LinkedList();//定义一个单链表
for (int i = 0; i < 1000; i++) {
//添加元素
list1.add(i);
list2.add(i);
}
long start = System.currentTimeMillis();//取出开在数组中进行查找的时间戳
for (int i = 0; i < 10000000; i++) {
list1.get(50);
}
long end = System.currentTimeMillis();//取出结束在数组中查找的时间戳
System.out.println((end - start) + "ms");//输出在数组中查找元素所用的时间
start = System.currentTimeMillis();//取出开在单链表中进行查找的时间戳
for (int i = 0; i < 10000000; i++) {
list2.get(50);
}
end = System.currentTimeMillis();//取出结束在单链表中查找的时间戳
System.out.println((end - start) + "ms");//输出在单链表中查找元素所用的时间
}
}
输出结果:
拓展
时间复杂度:用于描述算法的运行时间