手撕算法系列——1. 单链表逆转

    这道题是一道经典的算法题了,出没在各大厂小厂的面试题中,也出现在了我去年的考研题中,当时写的很烂,残念。。

    从考研题说起,当时题目的要求还比较严苛,要求不能借助额外的辅助空间,也就是要求完全通过操作指针来实现链表的逆转,查阅了一些资料,发现此题主要有两种解法——迭代法和递归法。

(1)迭代法

    迭代法用经典的“双指针法”遍历整个链表,其中cur指向当前结点,pre指向cur结点的前驱结点,同时用一个缓存tmp指向cur的后继结点,当cur不为空时,一直迭代执行以下操作:

    tmp = cur -> next

    cur -> next = pre

    pre = cur

    cur = tmp

遍历完成后,pre即指向新链表的头结点,而将原本头结点的指针域置为NULL即可。

C语言实现(这里仅给出结点类型和reverse函数):

接口:LinkNode *reverse(LinkNode *head);

输入:原链表的头结点

返回:逆转后链表的头结点

typedef struct LinkNode
{
	int data;    //假设值域为整型,无关紧要,甚至不要值域也行
	LinkNode *next;
}LinkNode;


LinkNode *reverse(LinkNode *head)
{
	LinkNode *pre = head;
	LinkNode *cur = head->next;
	LinkNode *tmp = NULL;
	while(cur)
	{
		tmp = cur->next;
		cur->next = pre;
		pre = cur;
		cur = tmp;
	}
	head->next = NULL;
	return pre;
}

(2)递归法

    用递归法逆转链表的思路则更为直接:若传入的结点有后继结点,则先对后继结点进行逆转操作,直至追溯至链表的尾结点,进行逆转操作,将当前结点的后继结点的后继指向自己,并将当前结点的指针域置为NULL即可。

C语言实现:

typedef struct LinkNode
{
	int data;    //假设值域为整型,无关紧要,甚至不要值域也行
	LinkNode *next;
}LinkNode;


LinkNode *reverse(LinkNode *head)
{
	if(head == NULL||head->next == NULL)
		return head; 			//若递归到尾结点,则开始回溯 
	LinkNode *rehead = reverse(head->next);   
	head->next->next = head;
	head->next = NULL;
	return rehead;
}

你可能感兴趣的:(算法题)