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]];}### 结构体指针
```cpptypedef 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] -> NULLprev 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-/