1011 字
5 分钟
链表完全版 C/C++(数组模拟/指针)

数组模拟(可实现指针链表的所有功能,在算法题中效率更高)#

int head; //头节点下标
int e[N]; //节点i的值,相当于结构体指针中的val
int ne[N]; //表示节点i的next指针是多少
int idx; //当前用到哪个节点
void init()
{
head = -1;
idx = 0;
}
void add_at_head(int x)
{
e[idx] = x;
ne[idx] = head;
head = idx;
idx++;
}
void add_at_k(int x , int k)
{
e[k] = x;
ne[idx] = ne[k];
ne[k] = idx;
idx++;
}
void remove(int k) //删除第k个点后面的点
{
ne[k] = ne[ne[k]];
}
### 结构体指针
```cpp
typedef struct ListNode {
int data;
ListNode* next;
} Node;
//创建新节点
Node* createNode(int data)
{
Node* newNode = (Node*) malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
//头插
void insertAtHead(Node** head , int x)
{
Node* newNode = createNode(x);
newNode ->next = *head;
*head = newNode;
}
#### 有同学可能会问:什么是*head ,什么是**head ?
在Node*head中,head是一个只想Node结构体的指针,他储存着链表头节点的地址,*head 代表作着Node结构,也就是头节点本身。
如果head指向某个节点,那么head存的是地址,*head存的是节点的内容(data和next)。
**head,是一个指向head指针的指针。因为如果要在函数内部修改head值,必须传递指针的指针。
因此在程序中,head是头指针的地址。  *head是头指针本身,储存着链表第一个头节点地址。
**newNode-.next = *head;  让新节点的next指向当前head所指向头节点**
***head= newNode; 让head指向newNode,使新节点成为链表新的头节点**
-----------------------------------------------------------------------------------------------
```cpp
//删除指定值节点
void deleteNode(Node** head, int x)
{
Node* temp = *head, *prev = NULL;
if(temp != NULL && temp -> data == x){ //如果头节点是要删除的节点
*head = temp -> next;
free(temp);
return;
}
while(temp != NULL && temp -> data != x){
prev = temp;
temp = temp -> next;
}
if(temp == NULL) return;
prev -> next = temp -> next;
free(temp);
}

**为什么要单独判断是否是头节点? **

未处理头节点:

void deleteNode(Node** head, int x) {
Node* temp = *head;
Node* prev = NULL;
while (temp != NULL && temp->val != x) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return; // 没找到
prev->next = temp->next; // 试图删除
free(temp);
}

如果删除的是头节点,则prev == NULL , 访问prev -> next 会导致段错误


//更新指定值的节点
void updateNode(Node* head, int x, int newData)
{
Node* temp = head;
while(temp != NULL && temp -> data != x){
temp = temp -> next;
}
if(temp == NULL) return;
temp -> data = newData;
}
//查找指定值的节点
Node* searchNode(Node* head,int x)
{
Node* temp = head;
while(temp != NULL)
{
if(temp -> data == x) return temp;
temp = temp -> next;
}
return NULL;
}

重点来了:反转链表

void reverseList(Node** head)
{
Node* prev = NULL;
Node* next = NULL;
Node* current = *head;
while(current != NULL){
next = current -> next; //记录下一个节点
current -> next = prev; //反转指针
prev = current; //更新prev
current = next; //移动current
}
*head = prev; //更新头节点
}

过程演示:

head -> [1] -> [2] -> [3] -> [4] -> NULL

prev current next 链表状态 NULL 1 2 1 -> NULL 1 2 3 2 -> 1 -> NULL 2 3 4 3 -> 2 -> 1 -> NULL 3 4 NULL 4 -> 3 -> 2 -> 1 -> NULL 4 NULL NULL 结束循环

head -> [4] -> [3] -> [2] -> [1] -> NULL
//成功反转

常见问题:链表反转过程中使用了几个指针?  三个。

1. prev(前驱指针):用于存储当前节点的前一个节点,初始值为 NULL。

2. current(当前指针):遍历链表,指向当前处理的节点,初始值为 *head(链表头)。

3. next(后继指针):用于暂存当前节点的下一个节点,防止断链。

//递归反转链表
Node* reverse(Node* head) {
if (head == NULL || head->next == NULL) {
return head;
}
Node* newHead = reverse(head->next); // 递归反转后续链表
head->next->next = head; // 将当前节点反向指向前一个节点
head->next = NULL; // 当前节点变为新链表的尾节点
return newHead; // 返回反转后的新头节点
}

原文发布于 CSDN:链表完全版 C/C++(数组模拟/指针)

链表完全版 C/C++(数组模拟/指针)
https://www.tommywutong.cn/posts/csdn-import/csdn-146347076--cc-/
作者
TommyWu
发布于
2025-03-28
许可协议
CC BY-NC-SA 4.0