链表逆置:是将形如 1 →2 →3 →4 →5 →NULL 的链表逆置改为:5 →4 →3 →2 →1 →NULL
对于这个问题,有两种方法:
1、采用三个指针:将整个链表翻转!!
时间复杂度O(N^2) 嵌套循环
具体思路如下:首先要先找到新的头结点,则需要一个指针pCur1遍历链表,找到原尾结点,将其设置为新的头结点,因为我们需要从原头结点开始遍历,则需要一个pOldHead指针来保存原头结点,现在在找一个pCur2来保存新链表的最后一个结点,每次遍历前将pCur1更新指向pOldHead,当pCur1的next恰好等于pCur2结点时,将pCur1尾插至pCur2,再更新pCur2和pCur1,最后当pOldHead等于pCur2时,逆置完毕,再将pCur2的next赋空即可!
代码如下:
void ReverseSList(PNode* pHead)
{
assert(*pHead); //参数检测
PNode pOldHead = *pHead;
PNode pCur2;
PNode pCur1;
if (NULL == *pHead) //空链表
{
printf("链表为空,无法逆置!!\n");
return;
}
pCur1 = *pHead;
while (pCur1->_pNext) //找到新的头结点 为原链表的尾结点
{
pCur1 = pCur1->_pNext;
}
*pHead = pCur1;
pCur2 = *pHead; //pCur2 指向逆置之后的头结点,插入一个结点,pCur2更新指向其next
pCur1 = pOldHead;
while (pCur2 != pOldHead) //当pCur2 == 原来的头结点时,逆置完毕,跳出循环
{
while (pCur2 == pCur1->_pNext) //当pCur1的next指向pCur2时
{
pCur2->_pNext = pCur1; // 将pCur2的next指向pCur1
pCur2 = pCur1; //并且更新pCur2 指向pCur1,
pCur1 = pOldHead; //pCur1重新指向原来的头结点
}
pCur1 = pCur1->_pNext; //pCur1从原头结点开始遍历链表,
}
pCur2->_pNext = NULL; //将尾指针的next赋空
}
2、采用头插的方法,不更新头结点
思路:大家知道链表的头插法的思路,将新的结点中的data与头结点data交换,然后将新结点插入到头结点的next处,从而达到看起来是头插的目的!
同样的:链表逆置也可以采用这种方法:从链表的第二个结点开始,将其结点的data用头插的方式插入到链表中,最终我们会得到:1 →2 →3 →4 →5 →4 →3 →2 →1 →NULL,,看到这个链表,我们是否应该想起,要将data为5的结点的下一个结点赋空,赋空之后,链表则成功逆置了!于是,在插入的过程中,我们需要一个标记的pIndex指针指向data为5的结点,具体怎么实现:可以知道第一个插入结点,于是
if (pHead->_pNext->_pNext == pWait) //在头结点的原本的第二个结点作为标记,逆置完毕后,其会成为新链表的尾结点
pIndex = pHead->_pNext;
就可以将其标记!
如图:
代码:
PNode ReverseSListOP(PNode pHead)
{
assert(pHead);
PNode pWait = pHead->_pNext;
PNode pIndex = NULL;
if (NULL == pHead)
{
printf("链表为空,无法逆置!!!\n");
return NULL;
}
for (; pWait != NULL; pWait = pWait->_pNext) //从头结点的第二个结点开始 头插
{
PNodePushFront(pHead, pWait->_data);
if (pHead->_pNext->_pNext == pWait) //在头结点的原本的第二个结点作为标记,逆置完毕后,其会成为新链表的尾结点
pIndex = pHead->_pNext;
}
if (pIndex != NULL)
pIndex->_pNext = NULL; //将标记的next赋空,即将尾结点的next赋空
return pHead;
}
关于链表具体怎么头插:我的另外一篇博客讲的详细 https://blog.youkuaiyun.com/code_zx/article/details/80024207
测试函数:
void testReverse()
{
PNode pHead;
PNode pos;
SListInit(&pHead);
PNodePushBack(&pHead, 1);
PNodePushBack(&pHead, 2);
PNodePushBack(&pHead, 3);
PNodePushBack(&pHead, 4);
PNodePushBack(&pHead, 5);
printSList(pHead);
ReverseSList(&pHead);
printSList(pHead);
pos = ReverseSListOP(pHead);
printSList(pos);
}
具体测试结果:
想了解关于链表的另外一些题,可以点一波关注,谢谢