链表是什么?为什么要使用链表?链表和数组的区别在哪里?等等这些都需要我们去解读的。我们学习链表的数据结构,就可以彻底的懂得计算机磁盘的底层存储结构的优缺点。让我们来开始链表的学习吧!
链表是一种物理存储单元上非连续、非顺序的存储结构。——摘自《百度百科》
其实,这么说是算是准确的,链表不讲究非得像数组一样顺序存储,所谓的顺序链表的存在也仅仅是数据的升序和降序的使用罢了。如果说数组有很多的有点,比如时间复杂度等等都比链表快,为什么还会存在链表呢?这就是数组存储和链式存储的问题了。举个例子,如果我们计算机磁盘是使用数组存储,那么我们把磁盘总容量分成一定数量分块,每块存储容量为一定的磁盘小分块,现在我刚从电脑里删除了一个200MB容量的文件,现在想装300MB的文件(假设)进入电脑中。根据数据顺序存储的性质,我删除了这个200MB文件后磁盘中将出现200MB空缺的磁盘容量,若装入300MB的文件需要另外在磁盘剩余充足的容量区域开辟一个300MB容量的内存空间来存储这个文件,如下图所示。
可以肯定的说,磁盘一定不是数组存储的,否则我的磁盘总是不被最大化利用,那得花多少钱去买多大的磁盘呀?
所以,磁盘是链式方式存储结构的 。
那么磁盘是链式存储的,那么它是怎么存的呢?如下图所示
很简单,先把200MB删除后磁盘空缺的空间占用,后100MB的就可以在磁盘的空余空间继续开辟空间。
链表的链式结构。这样的好处可以将剩余的空间很好的利用起来,将空间利用率达到最大化。坏处就是增删改查的时间复杂度相对于数组很慢。所以用某种数据结构前应该对实际情况进行思考和均衡才作出决定。
1.链表的结构
单向链表特点:
(1)存在唯一的一个被称作“第一个”的数据元素;
(2)存在唯一的一个被称为“最后一个”的数据元素;
(3)除第一个之外,集合中的每个数据元素均只有一个前驱;
(4)除了最后一个之外,集合中每个数据元素均只有一个后继。
这个什么意思呢?其实很简单,单向链表的每个空间对应一个数据,这就是一对一的关系,也就是所谓的线性结构。在JAVA中,建立链表是没有像C++等语言拥有指针的表达语法,但是存在类似于指针的概念,因为JVM的存在,所以JAVA建立指针空间指向的问题直接可以用等于号来处理 。如
node.next = por // node的下一个指针指向por空间
这个就是node的下个空间是por,让node—》por方式链接起来了。
2.链表的特点
链表的特点和上列的介绍差不多,拥有数组无法比拟的特点就是可以自由的在任意位置进行插入,而且不用数据扭动,而不像数组的插入数据后大规模的数据往前或者往后移动,所以比起数组的插入,链表的插入是很方便的。同时数组长度是固定的,链表的长度是可变的。(ArrayList除外,但是底层还是使用链表来实现)
这里附单向链表的代码
public class Nodetest {
private Node head; // 定义一个头节点
private static Node current; // 记录当前节点
private static int data;
public static void main(String[] args) {
Nodetest myList = new Nodetest();
for (int i = 0; i < 6; i++) {
myList.addData(i); // 循环添加5个元素
}
myList.printList(myList.head); // 打印链表
// // myList.addData(3);
// System.out.println();
// myList.printList(myList.head);// 缺少头插和中间插入函数
myList.increse(myList.head, 1, 8);
System.out.println();
myList.printList(myList.head);
// myList.searchdata(myList.head, 0);
// System.out.println();
// myList.change(myList.head, 2, 7);
// myList.printList(myList.head);
// System.out.println();
// myList.delData(myList.head,1);
// myList.printList(myList.head);
}
// 往链表中添加数据
private void addData(int data) {
if (head == null) {
head = new Node(data); // 如果头节点为空,就新建一个头结点
current = head; // 记录当前节点为头结点
} else {
current.next = new Node(data); // 新建一个节点,当前节点的指针域指向它
current = current.next; // 当前节点位置后移
}
}
// 打印链表
private void printList(Node head) {
if (head != null) { // 确定链表不为空
current = head;
if (current.next != null) { // 最后一个节点的为空
System.out.print(current.data + "-->");
current = current.next; // 当前节点往后移动一个位置
printList(current);
} else {
System.out.print(current.data);
}
}
}
// 寻找数据
private void searchdata(Node node, int data) {
if (node == null) {
System.out.println("找不到该数据");
} else {
if (node.data == data) {
System.out.println("找到了该数据" + node.data);
} else {
if (node.next != null) {
if (node.data == data) {
System.out.println("找到了该数据" + node.data);
} else {
node = node.next;
searchdata(node, data);
}
} else {
System.out.print("没有找到了数据");
}
}
}
}
// 改数据
private void change(Node node, int data, int newdata) {
if (head == null) {
System.out.println("链表没有数据,修改失败");
} else {
if (node.data == data) {
node.data = newdata;
} else {
if (node.next != null) {
if (node.data == data) {
System.out.println("找到了修改数据" + node.data);
node.data = newdata;
} else {
node = node.next;
change(node, data, newdata);
}
} else {
System.out.print("没有找到了修改的数据");
}
}
}
}
//全能添加
private void increse(Node node,int Currtdata,int insertData) {
/*
* 往后添加移动
*/
if (head == null) {
head = new Node(insertData); // 如果头节点为空,就新建一个头结点
current = head; // 记录当前节点为头结点
} else {
if (node.data == Currtdata) {
System.out.println("找到了该数据" + node.data);
} else {
if (node.next != null) {
if (node.data == Currtdata) {
System.out.println("增加该数据" + node.data);
Node newnode = null;
newnode.data = insertData;
newnode = node.next;
node = newnode;
} else {
node = node.next;
increse(node, Currtdata,insertData);
}
} else {
System.out.print("没有找到了数据");
}
}
}
}
// 删除
private void delData(Node node, int del) {
if (node == null) {
System.out.println("链表没有数据,删除失败");
}
else if(node.data == del){
System.out.println("找到了删除数据" + node.data);
head = node.next;//头部删除
node = null;
}
else {
if (node.next.next != null) {
if (node.next.data == del) {
System.out.println("找到了删除数据" + node.next.data);
Node temp;//建立一个指针指向。
temp = node.next;
node.next = node.next.next;//下个结点等于这个。
temp.next = null;
} else {
node = node.next;
delData(node, del);
}
} else {
if(node.next.data == del){
System.out.println("找到了删除数据" + node.next.data);
node.next = null;//尾部删除
}
else{System.out.print("没有找到了删除的数据");}
}
}
}
}
谢谢大家观看~~~比心~= ~=*