数据结构与算法-链表反转带头节点
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法-链表反转带头节点相关的知识,希望对你有一定的参考价值。
1.输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。
链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
分析:这是一道广为流传的微软面试题。由于这道题能够很好的反应出程序员思维是否严密,在微软之后已经有很多公司在面试时采用了这道题。
为了正确地反转一个链表,需要调整指针的指向。与指针操作相关代码总是容易出错的,因此最好在动手写程序之前作全面的分析。在面试的时候不急于动手而是一开始做仔细的分析和设计,将会给面试官留下很好的印象,因为在实际的软件开发中,设计的时间总是比写代码的时间长。与其很快地写出一段漏洞百出的代码,远不如用较多的时间写出一段健壮的代码。
最容易想到的第一种方法就是重新建立一个单链表newList,每次将list中的第一个结点放到newList后面。(头插法)
int ReverseSinglyListNode(ListNode *list) { ListNode *newList; //新链表的头结点 LNode *p,*q; //指向list的第一个结点,也就是要摘除的结点 p=List; //参数为空或者内存分配失败则返回NULL if (p == NULL || (newList = (ListNode *)malloc(sizeof(LNode))) == NULL) { return NULL; } //初始化newList newList->next = NULL; //依次将list的第一个结点放到newList的第一个结点位置 while (p->next != NULL) { q = p->next; newList->next = p->next; //头插法 p=newList->next; p=q; } //原头结点应该释放掉,并返回新头结点的指针 free(p); return newList; }
第二种方法是每次都将原第一个结点之后的那个结点放在list后面,下图是原始的单链表。
为了反转这个单链表,我们先让头结点的next域指向结点2,再让结点1的next域指向结点3,最后将结点2的next域指向结点1,就完成了第一次交换,顺序就变成了Header-结点2-结点1-结点3-结点4-NULL,然后进行相同的交换将结点3移动到结点2的前面,然后再将结点4移动到结点3的前面就完成了反转,思路有了,就该写代码了:
int ReverseSinglyLinkedList(ListNode *list) { LNode *p = NULL; LNode *q = NULL; if (list == NULL) return NULL; p = list->next; while (p->next != NULL) { q = p->next; p->next = q->next; q->next = list->next; list->next = q; } return list; }
以上是关于数据结构与算法-链表反转带头节点的主要内容,如果未能解决你的问题,请参考以下文章