一道算法题
逆转单链表
0->1->2->3->4
这道题,看起来非常简单,其实隐藏了许多知识点。
1. 知识点
首先,我们要知道结构体的定义,如何起别名,如何定义结构体指针。
这三点代码如下:
typdef struct node
{
int key;
struct node *next;
} Node;
- 结构体定义用struct关键字
- 起别名用typedef关键字
- 定义结构体指针
struct node *
2. 算法
这个算法其实蛮好想,就是要自己拿张草稿子画一画,就出来了。做题一定要心中有数,拿出你的笔和纸,心中有许多杂念,90%的我等凡夫俗子是想不清楚的。
闲话少扯,继续谈算法,我们首先想到的是,要改当前节点next指针,指向上一个节点,是不是首先要记录下一个节点,和上一个节点的位置?
所以我们需要3个指针:pre-记录上一个节点
,p-当前要改变的节点
, q-下一个节点
。
我们的思路就是:
- 先弄三个指针,记录开始的三个节点;
- 让当前节点next指针指向上一个节点;
- pre指向当前节点;当前节点指针 和下一个节点指针分别往后移动;
最后注意开头节点next = NULL, 和最后一个节点指向pre。
给出源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
int key;
struct node *next;
} Node;
Node* revertLinkList(Node *head)
{
if(head == NULL)
{
return NULL;
}
Node *p, *q, *pre;
// 三个指针,分别指向当前节点,后一个节点,上一个节点
p = head -> next;
q = p -> next;
pre = head;
while(q != NULL)
{
// 当前节点的next指针往前指
p -> next = pre;
printf("change key: %d\n", pre->key);
// 上一个节点指向当前节点
pre = p;
// 当前节点指针往后移,下一个节点指针也往后移
p = q;
q = q -> next;
// 继续下次循环
}
// 注意头节点next置空
p -> next = pre;
// 新的头节点指向他的上一个
head -> next = NULL;
return p;
}
/**
* 打印链表
*/
void outputLinkList(Node *head)
{
while(head != NULL)
{
printf("println key:%d\n", head->key);
head = head -> next;
}
}
int main()
{
Node *head = NULL;
Node *p, *pre;
head = malloc(sizeof(Node));
pre = head;
int n = 5;
int i = 1;
while(i < n)
{
p = malloc(sizeof(Node));
p -> key = i;
pre -> next = p;
pre = p;
i ++;
}
p -> next = NULL;
outputLinkList(head);
head = revertLinkList(head);
outputLinkList(head);
// 缺一步删除链表的操作
return 0;
}
总结来说,就是做算法脑子一定要非常清晰
,没有想清楚,请不要写代码。
以上是这次的分享。谢谢。