一:从尾到头打印单链表
思路:从尾到头,我们可以很容易想到使用函数递归的思想,要打印第一个节点,必须先打印第二个,要打印第二个必须先打印第三个……,所以这里方法最简单的就是用函数递归,代码实现如下:
void PrintSListFromTail2Head(PNode pHead)//将单链表头节点传过来
{
if (pHead->_pNext != NULL)
{
PrintSListFromTail2Head(pHead->_pNext);
}
printf("%d ", pHead->data);
return;
}
还有就是可以创建一个结构体数组,将单链表保存到数组中,然后从尾到头打印数组
二:删除无头单链表的非尾节点(不能遍历链表)
思路:因为是非尾节点,且不能遍历链表,找不到pos前面的那个节点,所以不能按照常规思路,找到pos前面的节点,让其_pNext指向pos后一个节点,只能删除pos后面的节点,并把后面的内容赋给pos,代码实现如下:
void DeleteListNotTailNode(PNode pos)
{
PNode pNext = pos->_pNext;
pos->data = pNext->data;//先将数据覆盖pos
pos->_pNext = pNext->_pNext;//再链接后面的节点
free(pNext);//释放节点
pNext = NULL;
}
三:在无头单链表一个节点前插入一个节点(不能遍历链表)
思路:与上题一样因为没有头节点,不能遍历链表,所以不可能找到pos前面的节点只能找到后面的节点,然后在那之间插入新节点,最后将新节点的内容与pos交换(因为人家让插到pos位置),代码实现如下:
void InesrtPosFront(PNode pos, DataType data)
{
PNode Next = pos->_pNext;//先保存pos的下一个节点
pos->_pNext = BuyNewNode(pos->data);//将新节点链接到pos后面,传pos的data为了避免以后再交换
pos->_pNext->_pNext = Next;//将pos之前的下个节点连接到新节点后面
pos->data = data;//将传过来的data覆盖原data
}
四:单链表实现约瑟夫环(Josephcircle)
思路:约瑟夫环:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人只剩一个,代码实现如下:
void JosephCircle(PNode* pHead, const int M)
{
assert(pHead);
while ((*pHead)->_pNext != *pHead)//等于说明只剩一个节点
{
PNode pCur = *pHead;
PNode pPre = *pHead;
int count = M;
while (--count)//注意,这里是前置--
{
pPre = pCur;
pCur = pCur->_pNext;
}
pPre->_pNext = pCur->_pNext;//链接链表
*pHead = pCur->_pNext;//改变头指针位置
free(pCur);
}
}
五:逆置/反转单链表
方法一:三指针,思路:将原本_pNext域指向下一个节点,改成指向上一个节点,就完成了逆置,代码事项如下:
void ReverseSList(PNode* pHead)
{
assert(pHead);
PNode pPre = NULL;
PNode pCur = *pHead;
PNode pNext = NULL;
if (NULL == *pHead)
return;
while (pCur)
{
pNext = pCur->_pNext;
pCur->_pNext = pPre;//将Next指针域指向上一个节点
pPre = pCur;
pCur = pNext;
}
*pHead = pPre;//pPre成为新的头节点
}
方法二头插法思路:创建一个头指针赋空,就然后将单链表从前到后每一个节点头插到创建的头指针中,代码实现如下:
PNode ReverseSListOP(PNode pHead)
{
PNode pCur = pHead;
PNode pNewHead = NULL;
while (pHead)
{
pCur = pHead;//进来就让pCur指向头部
pHead = pHead->_pNext;//头向后走一步
pCur->_pNext = pNewHead;//pCur插到新头部前
pNewHead = pCur;//新头为pCur
}
return pNewHead;
}
六:合并两个有序链表,合并后依然有序
思路:创建一个新头节点赋空,创建两个指针分别指向两个链表的头节点,从前到后开始比较,较大的尾插到新头节点,代码实现如下:
PNode MergeSList(PNode pHead1, PNode pHead2)
{
PNode pCur1 = pHead1;
PNode pCur2 = pHead2;
PNode pNewHead = NULL;
PNode pTail = NULL;//用来记录合并后链表的最后一个节点
if (NULL == pHead1)
return pHead2;
if (NULL == pHead2)
return pHead1;
//放pNewHead
if (pCur1->data < pCur2->data)
{
pNewHead = pCur1;
pCur1 = pCur1->_pNext;
}
else if (pCur1->data >= pCur2->data)
{
pNewHead = pCur2;
pCur2 = pCur2->_pNext;
}
//两链表中较小的节点尾插到pNewHead
pTail = pNewHead;
while (pCur1 && pCur2)//只要有一个链表为空就出来
{
if (pCur1->data < pCur2->data)
{
pTail->_pNext = pCur1;
pCur1 = pCur1->_pNext;
}
else if (pCur1->data >= pCur2->data)
{
pTail->_pNext = pCur2;
pCur2 = pCur2->_pNext;
}
pTail = pTail->_pNext;
}
if (pCur1)//说明pCur2为空
pTail->_pNext = pCur1;
else
pTail->_pNext = pCur2;
return pNewHead;
}