C语言实现字符串与单向链表逆序:代码示例及原理
在C语言开发中,处理数据结构的基础操作是面试与实战的重点。本文分别针对字符串逆序和单向链表逆序提供标准的代码实现与原理解析,前者利用指针双端交互技巧,后者采用经典的三指针迭代法。
字符串逆序
对于字符串(字符数组)的逆序,核心思路是利用两个指针分别从首尾向中间逼近,并交换所指位置的字符。这种方法空间复杂度为 O(1),且天然适合使用递归来简化代码结构。
第1步:定义递归交换函数
我们需要一个接收两个指针参数的函数。当左指针等于右指针时,说明已经遍历到中心,递归结束;否则进行值的交换,并向内收敛调用自身。
以下代码展示了不使用临时变量,仅通过算术运算完成整数类型值交换的逻辑(注:实际工程中建议直接使用 char temp = *p1; *p1 = *p2; *p2 = temp; 以提高可读性):
void stringReverse(char* p1, char* p2)
{
if (p1 == p2) return; // 基准情况:指针相遇或交错则返回
// 交换 *p1 和 *p2 的值(不依赖临时变量)
*p1 = (*p1) + (*p2);
*p2 = (*p1) - (*p2);
*p1 = (*p1) - (*p2);
// 递归条件:如果中间只有一个字符,无需继续
if (p1 == p2 - 1) return;
else stringReverse(++p1, --p2); // 指针向内移动并递归
}
第2步:调用示例
在实际使用中,需传入字符串的首地址及最后一个字符的地址(即长度减1的位置)。假设已定义包含内容的字符数组 str 并包含 string.h:
#include <string.h> // ... 初始化 str ... stringReverse(str, str + strlen(str) - 1);
单向链表逆序
链表逆序比字符串更复杂,因为内存地址不连续,必须改变节点的 next 指针指向。这里介绍最稳健的三指针迭代法(头插法的变种或直接反转邻接关系),它能避免断链导致的丢失问题。
第1步:数据结构定义
首先确保节点结构体定义正确,包含数据域和下一个节点的指针:
typedef struct Node {
int data;
struct Node* next;
} Node;
第2步:理解逆序状态变化
链表逆序的过程是将原本指向后方的 next 指针翻转指向前方。我们可以通过以下步骤观察变化:
初始状态如下所示,p1 指向头部节点:
执行一步逆序后,第一个节点的 next 变为 NULL,第二个节点开始接管后续逻辑,准备反转:
经过多次迭代后,整个链表方向完全颠倒,原本的尾部成为新的头部:
第3步:实现三指针迭代逻辑
为了安全地反转链表,我们需要三个辅助指针:p1 记录前一个节点(用于建立反向链接),p2 当前正在处理的节点,p3 记录下一个节点(防止断链丢失)。
- 边界检查:空链表或单节点链表直接返回。
- 初始化:
p1指向头节点,p2指向第二个节点,p3指向第三个节点。p1需要先将next置为NULL,因为它最终会变成新链表的尾节点。 - 循环反转:只要
p3不为空,就执行以下操作:将p2->next指向p1(完成当前节点的反转),然后所有指针整体向后移动一位。 - 收尾处理:当
p3为空时,说明只剩下最后两个节点(p1和p2),此时还需做一次反向链接,并将头指针head更新为新的头部p2。
Node* reverseLinkList(Node* head) {
// 边界情况:空链表或只有一个节点
if (head == NULL || head->next == NULL) {
return head;
}
Node* p1 = head; // 前驱节点
Node* p2 = p1->next; // 当前节点
Node* p3 = p2->next; // 后继节点
p1->next = NULL; // 原头节点变成尾节点,其next设为NULL
while (p3 != NULL) {
p2->next = p1; // 关键步骤:当前节点的next指向前驱,完成局部反转
p1 = p2; // 指针整体后移:前驱变为当前
p2 = p3; // 指针整体后移:当前变为后继
p3 = p3->next; // 指针整体后移:后继变为下下个节点
}
// 处理最后两个节点的反转
p2->next = p1;
// 更新头指针:原来的尾节点(现在的p2)是新链表的头
head = p2;
return head;
}
总结
字符串逆序利用索引/指针的物理相邻特性,通过递归可写出极其精简的代码。而链表逆序则考验对指针管理的细致程度,三指针法能有效避免因修改 next 指针而导致的链表断裂风险。以上关于C语言字符串与链表逆序操作的详细内容,更多关于C语言数据结构与算法的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









