单链表的逆置有多种方法可以实现,但根据时间复杂度来讲,最简单的方法有两种:
1.三个指针
typedef int DataType;//类型名重命名
typedef struct Node
{
struct Node* _pNext;
DataType _data;
}Node,*PNode;//定义一个单链表
PNode SListRever_ThreePoint(PNode pHead)
{
PNode pFirst = pHead;
PNode pMid = pHead->_pNext;
PNode pLast = pHead->_pNext->_pNext;//设置三个指针分别指向单链表的前三个节点
if (NULL == pHead)
return NULL;
pMid->_pNext = pFirst;//让中间的节点指向前面的节点
pFirst->_pNext = NULL;//将第一个节点的_next指针置空
pFirst = pMid;
pMid = pLast;
pLast = pLast->_pNext;//让三个指针分别向后前进一个节点
while (pLast)
{
pMid->_pNext = pFirst;
pFirst = pMid;
pMid = pLast;
pLast = pLast->_pNext;
}//当末尾的指针没有到NULL时,一直让中间的指针指向前面的指针
pMid->_pNext = pFirst;//跳出循环的时候,只剩下Mid指针没有指向First指针
return pMid;
}
画图理解:
2.头插法
在链表首个节点前插入它后面的节点。
typedef int DataType;//类型名重命名
typedef struct Node
{
struct Node* _pNext;
DataType _data;
}Node,*PNode;//定义一个单链表
void SlistRever_PushFront(PNode pHead)
{
PNode pfirst = pHead;
PNode pdel = NULL;
PNode pCur = pHead->_pNext;
while (pCur != NULL)
{
SListNodeInsertFront(pfirst, pCur->_data);//在第一个节点的前面插入一个节点
pdel = pCur;
pCur = pCur->_pNext;
SListErase(pHead, pdel);//删除被插入的节点
pfirst = pHead;
}
}
void SListNodeInsertFront(PNode pos,DataType data)
{
PNode NewNode = NULL;
if (NULL == pos)
{
printf("插入地址无效\n");
return 0;
}
else
{
NewNode = (PNode)malloc(sizeof(Node));
NewNode->_pNext = pos->_pNext;
pos->_pNext = NewNode;
NewNode->_data = pos->_data;
pos->_data = data;
}
}
void SListErase(PNode pHead, PNode pos)
{
PNode pdel = pHead;
PNode pback = pHead;
//assert(pHead);
if (NULL == pHead)
{
printf("链表为空\n");
}
else
{
while (pdel != pos)
{
pdel = pdel->_pNext;
if (pdel != pos)
pback = pback->_pNext;
}
pback->_pNext = pdel->_pNext;
free(pdel);
pdel = NULL;
}
}
画图理解: