关于单链表的倒置问题,有一个比较好的解法——头插法。
下面考虑包含头结点的单链表(头结点不算做第一个结点。下面提到结点时一般均是不算头结点的)
“头插法”思想描述:从链表的第一个结点开始,以每一个结点为单位,遍历链表,将遍历到的结点依次插入到头结点的后面。
下面先给出链表的结构体定义
<span style="font-size:18px;">//定义链表结构体
typedef struct LinkNode
{
int data; //数据域
struct LinkNode *next; //指针域
}*LinkList,LNode;
</span>
头插法实现链表倒置
<span style="font-size:18px;">//链表反转
LNode *LinkListReverse(LinkList head)
{
//Description:以头插法实现链表的反转,head指针不动,从第一个结点开始一直将后续结点插入head之后.
//依次将第一个结点到最后一个结点插入头结点与第一个结点(不断变化)之间即可(只有一个结点时也相同操作)
//<span style="font-family: Arial, Helvetica, sans-serif;">判断输入是否合法</span>
if(NULL == head)
{
std::cout<<"The input is NULL."<<endl;
return -1;
}
//初始化
LinkList pcurr,ptemp; //当前指向的结点对应指针为pcurr,ptemp是临时指针
pcurr = head->next;
head->next=NULL; //当只有一个结点时,此句很有用
while(NULL != pcurr)
{
ptemp = pcurr->next; //存下未遍历的结点
pcurr->next = head->next; //将当前遍历的结点脸上第一个结点
head->next = pcurr; //将头结点连上当前遍历的结点
pcurr = ptemp; //遍历下一个结点
}//endwhile
return head;
}//endLinkListReverse</span>
测试用例
**链表为空
**链表只有一个结点
**链表有多个结点(两个,三个…)
在何海涛的《剑指Offer》一书中也有单链表的倒置问题,但用的是不同的解法。可见某博主的blog文章<程序员面试题精选100题(19)-反转链表[数据结构]>,当然也有网友在文章评论里提到了头插法,但博主的回复有避锋之嫌,个人建议博主应早日更新,以防误导读者。
扩展:
归并两个有序递增单链表成一个递减单链表(从两个链表中选取元素比较出较大值头插法入,然后较大值所在的链表后移一步…最后不要忘了将没插完的链表一次性倒序插入) ps:此题若要求存储空间不变,则是将一个链表插入另一个链表中,可见<归并两个有序递增单链表成一个递减单链表,存储空间不变,要求时间复杂度最小>