一,基础概念
链表是一种线性表结构,节点是链表中的基本单元。
链表是节点的集合,节点可以分布在内存中的任何位置,每个节点都存储着链表中下一个节点的地址。
如图,看似随意摆放的各个节点,其内部其实有链表维持的相对位置信息。

我们用"指针"来表示链表中的方向,为了维持节点之间的先后顺序,链表给每个节点都附加了一个指针。单链表中的每个节点都包含指向后一个节点的后向指针,双链表中的每个节点不仅包含指向后一个节点的后向指针,也包含指向前一个节点的前向指针。链表在内存上不一定是连续分布的,我们只能沿着指针的方向迭代遍历链表上的节点,无法直接根据下标来访问链表指定位置上的元素。
链表和数组相比,主要优势:
1.链表在编译期不需要知道具体大小。
2.数组中的元素在内存中是连续分布的,且以相同距离间隔开。因此,往数组中插入新的元素就需要移动数组中的其他数据,链表不需要这么麻烦。
数组的内存分布:

链表的内存分布:

二,链表的图示结构
不包含头节点和尾节点的链表:

包含头节点和尾节点的链表:

三,节点的代码表示
以单链表为例,节点的组成:
1,数据域:节点的元素值
2,指针域:指向下一个节点的指针
Python实现:
python
class Node:
def __init__(self, value):
self.data = value
self.next = None
C++实现:
cpp
struct Node {
int value; //节点的元素值,假设存储的元素是int类型
Node *next; //后向指针
Node(int val = 0) { value = val; next = NULL; } //构造函数
};
如果要实现双链表,且用泛型来表示元素值的类型,可以这样实现节点:
cpp
template <typename T>
struct Node {
T value; //节点的元素值
Node *next; //后向指针
Node *prev; //前向指针
Node() { next = NULL; prev = NULL; } //默认构造函数
Node(const T &val) { value = val; next = NULL; prev = NULL; } //初始化元素值的构造函数
};
四,链表常见操作
1.初始化和使用链表
Python实现:
python
class Node:
def __init__(self, item):
self.item = item
self.next = None
class LinkedList:
def __init__(self):
self.head = None
if __name__ == '__main__':
linkedList = LinkedList()
linkedList.head = Node(1)
second = Node(2)
third = Node(3)
#连接各个节点
linkedList.head.next = second
second.next = third
while linkedList.head != None:
print(linkedList.head.item, end=" ")
linkedList.head = linkedList.head.next
C++实现:
cpp
#include <iostream>
using namespace std;
class Node {
public:
int value;
Node* next;
};
int main() {
Node* head;
Node* one = NULL;
Node* two = NULL;
Node* three = NULL;
one = new Node();
two = new Node();
three = new Node();
one->value = 1;
two->value = 2;
three->value = 3;
//连接各个节点
one->next = two;
two->next = three;
three->next = NULL;
head = one;
while (head != NULL) {
cout << head->value << endl;
head = head->next;
}
}
2.链表往后追加节点

Python实现:
python
def append(self, new_element):
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new_element
else:
self.head = new_element
C++实现:
cpp
class Node
{
public:
int data;
Node* next;
};
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node();
Node* last = *head_ref;
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
while (last->next != NULL)
{
last = last->next;
}
last->next = new_node;
return;
}
3.链表指定位置添加节点

Python实现:
python
def insert(self, new_element, position):
counter = 1
current = self.head
if position > 1:
while current and counter < position:
if counter == position - 1:
new_element.next = current.next
current.next = new_element
current = current.next
counter += 1
elif position == 1 :
new_element.next = self.head
self.head = new_element
C++实现:
cpp
class Node
{
public:
int data;
Node *next;
};
void insert(Node* prev_node, int new_data)
{
if (prev_node == NULL) {
cout << "The given previous node cannot be NULL";
return;
}
Node* new_node = new Node();
new_node->data = new_data;
//最核心的两步
new_node->next = prev_node->next;
prev_node->next = new_node;
}
4.获得链表长度
Python实现:
python
def getlength(self):
current = self.head
count = 0
while current.next:
count = count + 1
current = current.next
return count
C++实现:
cpp
int getlength(Node* head)
{
int count = 0;
Node* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
5.删除指定节点
具体操作: 将前一个节点的next指针指向被删除节点的下一个节点
Python实现:
示意图:

python
def delete(self, value):
current = self.head
previous = None
while current.value != value and current.next:
previous = current
current = current.next
if current.value == value:
if previous:
previous.next = current.next
else:
self.head = current.next
C++实现:
cpp
typedef struct Node {
int data;
struct Node* next;
} Node;
void delete(Node** head, int position)
{
Node* temp;
Node* prev;
temp = *head;
prev = *head;
for (int i = 0; i < position; i++) {
if (i == 0 && position == 1) {
*head = (*head)->next;
free(temp);
}
else {
if (i == position - 1 && temp) {
prev->next = temp->next;
free(temp);
}
else {
prev = temp;
if (prev == NULL)
break;
temp = temp->next;
}
}
}
}
6.查询某节点是否存在
Python实现:
python
def search(self, item):
current = self.head
found = False
while current != None and not found:
if current.value == item:
found = True
else:
current = current.next()
return found
C++实现:
cpp
class Node {
public:
int data;
Node* next;
};
bool search(Node* head, int x)
{
Node* current = head;
while (current != NULL) {
if (current->data == x)
return true;
current = current->next;
}
return false;
}
五,链表的主要使用场景
如果应用场景包含很多查询操作,此时更适合使用数组。如果应用场景中,需要使用的元素个数不确定,且需要经常对元素进行添加和删除操作,此时使用链表结构会更合适。简单概括就是,链表适合使用在频繁增删的场景,数组适合使用在频繁查询的场景。
六,参考阅读
《Problem Solving with Algorithms and Data Structures Using Python, Second Edition》
https://www.programiz.com/dsa/linked-list
https://www.geeksforgeeks.org/what-is-linked-list/?ref=lbp
https://gist.github.com/bavly/ef45e5b9db7d9a400b51ec132f553a0a
https://pumpkinprogrammerdotcom4.wordpress.com/2014/06/13/c-tutorial-intro-to-linked-lists/