一、从尾到头打印单链表
法一:递归法
void SListNodeRecurReversePrint(SListNode *pHead)
{
if (pHead == NULL)
return;
SListNodeRecurReversePrint(pHead->pNext);
printf("%d <- ", pHead->data);
}
法二:常规法
void SListNodeTwoPrint(SListNode *pHead)
{
assert(pHead);
SListNode *pEnd = NULL;
while (pEnd != pHead)
{
SListNode *pCur = pHead;
while (pCur->pNext != pEnd)
{
pCur = pCur->pNext;
}
pEnd = pCur;//使pEnd前进一位
printf("%d <- ", pEnd->data);
}
printf("\n");
}
二、逆置/反转单链表(返回一个新的单链表)
法一:头删头插法
SListNode *SListNodeInverse1(SListNode **ppHead)
{
assert(ppHead);
if (!(*ppHead)->pNext)
{
return *ppHead;
}
SListNode *pNewList = NULL; // 新链表
SListNode *p = *ppHead; // 老链表
SListNode *q = NULL; // 准备头插的
while (p)
{
q = p; p = p->pNext;
q->pNext = pNewList;
pNewList = q;
}
return pNewList;
}
法二:p1,p2,p3改变头结点
void SListNodeInverse2(SListNode **ppHead)
{
SListNode *p1 = NULL;
SListNode *p2 = *ppHead;
SListNode *p3 = (*ppHead)->pNext;
assert(ppHead);
if (*ppHead == NULL || (*ppHead)->pNext == NULL)
return;
while (1)
{
p2->pNext = p1;
p1 = p2;
p2 = p3;
if (p2 == NULL)
break;
p3 = p3->pNext;
}
*ppHead = p1;
}
三、删除一个无头单链表的非尾结点(不能遍历单链表)
方法:替换删除(不能删除当前结点,那我们就删除后面一个节点,并修改当前结点内容)
void DeleteNode(SListNode *pos, DataType data)
{
//1 30 3 4
SListNode *cur = pos->pNext;
pos->data = cur->data;
pos->pNext = cur->pNext;
free(cur);
}
四、在无头单链表的一个节点之前插入一个结点(不能遍历单链表)
方法:替换插入(不可以在前面插入,那我们就在他后面插入,并修改相关内容)
void InsertNode(SListNode *pos, DataType data)
{
assert(pos);
SListNode *next = pos->pNext;
SListNode *NewNode = BuyMemory(data);//直接插入当前结点的数据域,有利于不用修改插入结点的值
pos->pNext = NewNode;
NewNode->pNext = next;
pos->data = 30;
}
五、单链表实现约瑟夫环
void SListNodeJosephCircle(SListNode *pHead,DataType k)
{
assert(pHead);
SListNode *cur = pHead;
//构建一个循环列表
while (cur->pNext!=NULL)
{
cur = cur->pNext;
}
cur->pNext = pHead;
//从头开始循环
cur = pHead;
while (cur->pNext != cur)
{
int count = k;
//每次循环k-1次
while(--count)
{
cur = cur->pNext;
}
//利用替换删除
SListNode *pre = cur->pNext;
cur->data = pre->data;
cur->pNext = pre->pNext;
free(pre);
}
printf("%d \n", cur->data);
}