目录
单链表的概念:
首先,单链表是什么东西呢?
单链表的概念出自数据结构
链表是通过一组一组任意的存储单元来存储线性表中的数据元素,由一个个节点构成。线性表:线性的结构,它是一个含有n>=0个结点的有限序列。
有且只有一个上一个结点,有且只有一个下一个结点。(有头有尾的一条线)
单向链表:在维护一个结点的自身的值的同时,还要维护它的下一个值的指向地址
示意图:
单链表的实现:
Node类:
储存输入的数据(data)和下一个节点地址(next)。
public class Node {
private Integer data;//存储的是输入的数据
private Node next;//引用数据类型,指的是下一个结点地址
public Node(){}
public Node(Integer data, Node next) {
this.data = data;
this.next = next;
}
public Integer getData() {
return data;
}
public void setData(Integer data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", next=" + next +
'}';
}
}
Link类:
以下内容都在Link类里,为了方便一个一个功能的观看,所以我给他分开了
public class Link {
//链表的长度
private int size;
//链表的第一个结点
private Node first;
//链表的最后一个结点
private Node last;
public Link() {
}
//获取长度
public Integer size(){
return size;
}
}
在链表尾部添加结点:
//添加到链表尾部
public boolean add(Integer data) {
//把传入的数据构建成一个结点
Node node = new Node(data, null);
//如果现在链表时空的,我就是第一个结点
if (first == null) {
first = node;
} else {
//如果链表不是空,那我就是最后一个结点
//我应该是往原来的last结点后面
//我是原来last结点的下一个结点
last.setNext(node);
}
last = node;
size++;
return true;
}
在指定的位置添加结点
public boolean add(Integer data, int index) {
Node node = getN(index - 1);
Node newNode = new Node(data, null);
if (node != null) {
Node next = node.getNext();
newNode.setNext(next);
node.setNext(newNode);
} else {
first = newNode;
last = newNode;
}
size++;
return true;
}
删除尾部的结点:
//删除最后一个元素
public boolean delLast() {
if (size <= 0) {
return false;
}
if (size == 1) {
first=null;
last=null;
return true;
}
if (last != null) {
last = getN(size - 2);
size--;
}
return true;
}
删除第一个结点:
//删除第一个元素
public boolean delFirst() {
if (size <= 0) {
return false;
}
if (first != null) {
first = first.getNext();
size--;
}
return true;
}
删除指定位置结点:
//删除指定位置元素
public boolean del(int index){
if(size<0){
return false;
}
if(size==1){
first=null;
last=null;
}else{
Node node=getN(index-1);
node.setNext(node.getNext().getNext());
}
size--;
return true;
}
修改指定结点的内容:
//修改指定目标地点的元素
public boolean insert(Integer data,int index){
Node node=getN(index);
node.setData(data);
return true;
}
根据下标获取指定结点:
//根据下标获取指定的结点:
//获取index
public Node getN(int index) {
if (index < 0) {
index = 0;
}
if (index >= size - 1) {
index = size - 1;
}
//找到第index个
Node cursor = first;
for (int i = 0; i < index; i++) {
cursor = cursor.getNext();
}
return cursor;
}
根据下标获取指定的数据:
//根据下标获取指定的数据:
public Integer getNode(int index){
return getN(index).getData();
}
测试类:
操作以下检验是否功能是否成功:
public static void main(String[] args) {
Link link=new Link();
link.add(1);
link.add(2);
link.add(3);
link.add(4);
System.out.println(link.getN(0));
link.add(9, 2);
link.add(8, 1);
System.out.println(link.getN(0));
link.del(2);
System.out.println(link.getN(0));
}
}
运算结果:
这样观看结果,就能看出结点与结点之间的关系了,但是呢,会不会有人说用数组不是更好吗,我们之前都是用数组来表示的,也写过数组的增删改查。
在内存中,数组和链表都是基本的数据结构
数组和链表的优缺点:
对比以下数组和链表的优缺点:
1.数组进行大数据的增删运算时,运算量会非常的大,移位,扩容,空间和时间复杂度都会很大。
2.链表进行大数据的增删运算时,运算量非常少,因为每一个结点都是独立的,所以只需要改上一个结点和下一个结点链接的地址就好了
3.数组进行查找运算时,是非常简单的,而链表进行查找运算时,是非常麻烦的。一个一个地址的寻找会非常麻烦,而数组就直接通过下标来进行查找就行。