思想:
单链表中体现数据结构学习中的一个重要的算法操作思想。就是要学习这些数据元素的联系规律,如何传递结点中的next域,在单链表中,有且只有一个作用记录了联系,这个就是当前结点的next存储了下一个结点的地址。
结论:只要我们在设计这些元素运动的重复过程(写循环),这些元素的相对位置不发生变化,那么这个过程就是可以重复的。
如下代码:使用两种方法进行顺序链表的转换。
#include <stdio.h>
#include <stdlib.h>
//链表中节点的结构
typedef struct Link {
int elem;
struct Link *next;
}link;
//初始化链表的函数
link * initLink();
//用于输出链表的函数
void display(link *p);
//迭代法反转链表
link * iteration_reverse(link* head);
//头插法反转链表
link * head_reverse(link * head);
//就地逆置法反转链表
link * local_reverse(link * head);
int main() {
link*p = NULL;
//初始化链表(1,2,3,4)
printf("初始化链表为:\n");
p = initLink();
display(p);
p = iteration_reverse(p);
display(p);
p = head_reverse(p);
display(p);
p = local_reverse(p);
display(p);
return 0;
}
link * initLink() {
int i = 0;
link * temp = NULL;
link * p = (link*)malloc(sizeof(link));//创建头节点
//首元节点先初始化
p->elem = 0;
p->next = NULL;
temp = p;//头指针指向头节点
for (i = 1; i < 5; i++) {
link *a = (link*)malloc(sizeof(link));
a->elem = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
//迭代反转法,head 为有头节点链表的头指针
link * iteration_reverse(link* head) {
//如果该链表为 NULL,或者没有存储数据,又或者只存有 1 个数据
if (head == NULL || head->next == NULL || head->next->next == NULL) {
return head;
}
else {
link * beg = NULL;
link * mid = head->next;
link * end = head->next->next;
//一直遍历
while (1)
{
//修改 mid 所指节点的指向
mid->next = beg;
//此时判断 end 是否为 NULL,如果成立则退出循环
if (end == NULL) {
break;
}
//整体向后移动 3 个指针
beg = mid;
mid = end;
end = end->next;
}
//最后修改 head 头指针的指向
head->next = mid;
return head;
}
}
//头插法反转链表
link * head_reverse(link * head) {
//为新节点添加头节点
link * new_head = (link*)malloc(sizeof(link));
new_head->elem = 0;
new_head->next = NULL;
link * temp = NULL;
if (head == NULL || head->next == NULL || head->next->next == NULL ) {
return head;
}
while (head->next != NULL)
{
temp = head->next;
//将 temp 从 head 中摘除
head->next = head->next->next;
//将 temp 插入到 new_head 的头部
temp->next = new_head->next;
new_head->next = temp;
}
return new_head;
}
//就地逆置法
link * local_reverse(link * head) {
link * beg = NULL;
link * end = NULL;
if (head == NULL || head->next == NULL || head->next->next == NULL) {
return head;
}
beg = head->next;
end = head->next->next;
while (end != NULL) {
//将 end 从链表中摘除
beg->next = end->next;
//将 end 移动至链表头
end->next = head->next;
head->next = end;
//调整 end 的指向,另其指向 beg 后的一个节点,为反转下一个节点做准备
end = beg->next;
}
return head;
}
void display(link *p) {
link* temp = p->next;//将temp指针重新指向首元结点
//只要temp指针指向的结点的next不是Null,就执行输出语句。
while (temp) {
printf("%d ", temp->elem);
temp = temp->next;
}
printf("\n");
}