一、单链表的特点
链表以结点作为存储单元,这些存储单元可以是不连续的。单链表每个结点由两部分组成:存储的数值+后序结点的指针,下面均是单链表的操作。
上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一个节点,就这样一节一节往下面记录,直到最后一个节点,其中的next指向null。(网络引用)
二、实战(废话不多说,直接上机开干)
class Node {
///数据域
int data;
下一个结点
Node next;
Node(int data){
this.data = data;
}
}
class LinkList {
Node head;
void addNode(Node data) {
if (head == null) {
head = data;
return;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = data;
}
///插入到指定位置
void insertNodeByIndex(int index, Node newNode) {
if (index < 0 || index > getLength()) {
print("插入位置不合法");
}
if (head == null) {
head = newNode;
return;
}
int len = 0;
Node temp = head;
while (temp.next != null) {
len++;
if (len == index) {
newNode.next = temp.next;
temp.next = newNode;
break;
}
temp = temp.next;
}
}
Node removeAt(int index) {
if (index < 0 || index > getLength()) {
return null;
}
if (head == null) {
return null;
}
if (index == 0) {
//删除头结点
head = head.next;
return head;
}
Node temp = head;
Node delNode;
int len = 0;
while (temp.next != null) {
len++;
if (len == index) {
delNode = temp.next;
temp.next = temp.next.next;
break;
}
temp = temp.next;
}
return delNode;
}
bool remove(Node node) {
if (node == null) {
return false;
}
if (head == null) {
return false;
}
if (node.data == head.data) {
//删除头结点
head = head.next;
return true;
}
Node temp = head;
bool isSuccess = false;
while (temp.next != null) {
if (temp.next.next == node.next) {
temp.next = node.next;
isSuccess = true;
break;
}
temp = temp.next;
}
return isSuccess;
}
int getLength() {
if (head == null) {
return 0;
}
int len = 0;
Node temp = head;
while (temp.next != null) {
temp = temp.next;
len++;
}
return len;
}
///查找元素
Node findNodeByIndex(int index) {
if (index < 0 || index > getLength()) {
return null;
}
if (head == null) {
return null;
}
Node temp = head;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp;
}
///遍历
void printLink() {
Node curNode = head;
while (curNode != null) {
print(curNode.data);
curNode = curNode.next;
}
}
}
测试类
LinkList list = new LinkList();
Node node1 = Node(1);
Node node2 = Node(2);
Node node3 = Node(3);
list.addNode(node1);
list.addNode(node2);
list.addNode(node3);
Node node4 = Node(4);
list.insertNodeByIndex(1, node4);
print("删除前:");
list.printLink();
list.remove(node4);
print("删除的元素:${list.removeAt(1).data}");
print("删除后:");
list.printLink();
print("查找元素:${list.findNodeByIndex(1).data}");
三、链表的总结
单链表、循环链表、双向链表的比较
链表结构 | 优点 | 缺点 |
---|---|---|
单链表 | 1、在找出节点后,插入和删除速度相较于顺序表更快 2、不需要预分配空间,元素个数不受限制 | 查找数据元素的速度相较于顺序表更慢 |
循环链表 | 在单链表的基础上进一步改进,遍历的时候可以从任意结点开始,增加了遍历的灵活性 | 没有解决单链表查找元素速度较慢的问题 |
双向链表 | 在单链表的基础上进一步改进,查找元素可以反向查找前缀结点,一定程度上提升了查找数据元素的速度 | 需要记录前缀结点,增加了额外的内存空间开销 |
静态链表 | 在插入和删除操作时,不需要移动元素,只需要修改游标,改进 了顺序表插入和删除需要移动元素的缺点 | 1、没有解决顺序表表长难以确定的问题 2、失去了顺序表随机存储的特性 |