单链表基本功能实现:
https://blog.csdn.net/W_J_F_/article/details/80007864
ListNode.h
// 逆序打印单链表
void PrintSListFromTail(pNode pHead);
// 删除链表的非尾结点,要求:不能遍历链表
void DeleteListNotTailNode(pNode *pHead, pNode pos);
// 查找链表的中间结点,要求只能遍历一次链表
pNode FindMiddleNode(pNode pHead);
// 查找链表的倒数第K个结点,要求只能遍历一次链表
pNode FindLastKNode(pNode pHead, int K);
// 删除链表的倒数第K个结点,要求只能遍历一次链表
pNode DeleteLastKNode(pNode pHead, int K);
// 用单链表实现约瑟夫环
int JosephCircle(pNode* pHead, const int M);
// 链表的逆置--三个指针
void ReverseSList(pNode* pHead);
// 链表的逆置--头插法
pNode ReverseSListOP(pNode pHead);
// 用冒泡排序思想对单链表进行排序
void BubbleSort(pNode pHead);
// 合并两个有序单链表,合并后依然有序
pNode MergeSList(pNode pHead1, pNode pHead2);
// 判断两个单链表是否相交---链表不带环
int IsSListCross(pNode pHead1, pNode pHead2);
// 求两个单链表相交的交点---链表不带环
pNode GetCorssNode(pNode pHead1, pNode pHead2);
ListNode.c
// 逆序打印单链表
void PrintSListFromTail(pNode pHead)
{
if (NULL == pHead)
{
return;
}
PrintSListFromTail(pHead->_pnext);
printf("%d-> ",pHead->_pdata);
}
// 删除链表的非尾结点,要求:不能遍历链表
void DeleteListNotTailNode(pNode *pHead,pNode pos)
{
assert(pHead);
if (NULL == *pHead || NULL == pos)//可能改变头结点指向时传二级指针
{
return;
}
//要删除节点为头节点和非头结点两种情况
if (pos == *pHead)
{
pNode pDel = *pHead;
*pHead = (*pHead)->_pnext;
free(pDel);
}
else
{
pNode pDel = pos;
pDel = pDel->_pnext;
if (pDel->_pnext)
{
pos->_pdata = pDel->_pdata;
pos->_pnext = pDel->_pnext;
free(pDel);
}
}
}
// 查找链表的中间结点,要求只能遍历一次链表
pNode FindMiddleNode(pNode pHead)
{
if (NULL == pHead)
{
return NULL;
}
//偶数个和奇数个节点
pNode pFas = pHead;
pNode pLow = pHead;
pNode pPre = NULL;
while (pFas && pFas->_pnext)
{
pPre = pLow;
pLow = pLow->_pnext;
pFas = pFas->_pnext->_pnext;
}
//如果pFas为空,有偶数个节点,如果pFas->_pnext为空,有奇数个节点
if (NULL == pFas)
{
return pPre;
}
else
{
return pLow;
}
}
// 查找链表的倒数第K个结点,要求只能遍历一次链表
pNode FindLastKNode(pNode pHead, int K)
{
if (NULL == pHead || K <= 0)
{
return NULL;
}
pNode pFir = pHead;
while (K--)//第一个指针走k步
{
if (NULL == pFir)
{
return NULL;
}
pFir = pFir->_pnext;
}
pNode pSec = pHead;
while (pFir)//第一个指针向后走(N(总数)- k)步
{
pFir = pFir->_pnext;
pSec = pSec->_pnext;//相当于第二个指针倒着走k步
}
return pSec;
}
// 删除链表的倒数第K个结点,要求只能遍历一次链表
pNode DeleteLastKNode(pNode pHead, int K)
{
if (NULL == pHead || K <= 0)
{
return NULL;
}
pNode pFir = pHead;
while (K--)//第一个指针走k步
{
if (NULL == pFir)
{
return NULL;
}
pFir = pFir->_pnext;
}
pNode pSec = pHead;
pNode pPre = NULL;
while (pFir)//第一个指针向后走(N(总数)- k)步
{
pPre = pSec;
pFir = pFir->_pnext;
pSec = pSec->_pnext;//相当于第二个指针倒着走k步
}
if (pHead == pSec)
{
pNode pNew = pHead;
pHead = pHead->_pnext;
free(pNew);
return pHead;
}
else
{
pPre->_pnext = pSec->_pnext;
free(pSec);
return pHead;
}
}
// 用单链表实现约瑟夫环
int JosephCircle(pNode* pHead, const int M)
{
assert(pHead);
if (NULL == *pHead || M <= 1) {
return -1;
}
pNode pStr = *pHead;
pNode pCur = NULL;
while (pStr->_pnext != pStr) {
//报数
int count = M;
while (--count) {
pCur = pStr;
pStr = pStr->_pnext;
}
//剔除
pCur->_pnext = pStr->_pnext;
free(pStr);
pStr = pCur->_pnext;
}
return pStr->_pdata;
}
// 链表的逆置--三个指针
void ReverseSList(pNode* pHead)
{
assert(pHead);
if (NULL == *pHead)//可能改变头结点指针指向传二级指针
{
return;
}
pNode pCur = *pHead;
pNode pNex = pCur;
pNode pPre = NULL;
while (pCur)
{
pNex = pCur->_pnext;
pCur->_pnext = pPre;
pPre = pCur;
pCur = pNex;
}
*pHead = pPre;
}
// 链表的逆置--头插法
pNode ReverseSListOP(pNode pHead)
{
if (NULL == pHead)
{
return NULL;
}
pNode pCur = NULL;
pNode pNew = NULL;
//处理第一个节点
pNew = pHead;
pHead = pHead->_pnext;
pNew->_pnext = NULL;
while (pHead)
{
pCur = pHead->_pnext;
pHead->_pnext = pNew;
pNew = pHead;
pHead = pCur;
}
return pNew;
}
// 用冒泡排序思想对单链表进行排序
void BubbleSort(pNode pHead)
{
if (NULL == pHead)
{
return;
}
pNode pTail = pHead;
while (pTail->_pnext)
{
pTail = pTail->_pnext;
}
pNode pCur = NULL;
pNode pPre = NULL;
while (pTail != pHead)//pTail指向头说明只有一个节点,不需要再比较
{
pCur = pHead;
while (pCur != pTail)
{
if ((pCur->_pdata) > (pCur->_pnext->_pdata))
{
int tmp = pCur->_pdata;
pCur->_pdata = pCur->_pnext->_pdata;
pCur->_pnext->_pdata = tmp;
}
pPre = pCur;
pCur = pCur->_pnext;
}
pTail = pPre;
}
}
// 合并两个有序单链表,合并后依然有序
pNode MergeSList(pNode p1, pNode p2)
{
pNode pNew = NULL;
//处理头结点
if (p1 && (p1->_pdata <= p2->_pdata))
{
pNew = p1;
p1 = p1->_pnext;
}
else if (p2)
{
pNew = p2;
p2 = p2->_pnext;
}
pNode pNewHead = pNew;
//如果p1,p2都存在节点
while (p1 && p2)
{
if (p1->_pdata <= p2->_pdata)
{
pNew->_pnext = p1;
p1 = p1->_pnext;
}
else
{
pNew->_pnext = p2;
p2 = p2->_pnext;
}
pNew = pNew->_pnext;
}
//p1或者p2为空
if (p1)
{
pNew->_pnext = p1;
}
else
{
pNew->_pnext = p2;
}
return pNewHead;
}
// 判断两个单链表是否相交---链表不带环
int IsSListCross(pNode pHead1, pNode pHead2)
{
if (NULL == pHead1 || NULL == pHead2)
{
return -1;
}
//找到两个链表的最后一个节点
while (pHead1->_pnext)
{
pHead1 = pHead1->_pnext;
}
while (pHead2->_pnext)
{
pHead2 = pHead2->_pnext;
}
//相交节点只可能是y型,不可能是x型,因为一个节点只有一个后继
if (pHead1 == pHead2)
{
return 1;
}
else
{
return -1;
}
}
// 求两个单链表相交的交点---链表不带环
pNode GetCorssNode(pNode pHead1, pNode pHead2)
{
if (NULL == pHead1 || NULL == pHead2)
{
return NULL;
}
int len1 = 0;
int len2 = 0;
pNode pCur1 = pHead1;
pNode pCur2 = pHead2;
while (pCur1)
{
len1++;
pCur1 = pCur1->_pnext;
}
while (pCur2)
{
len2++;
pCur2 = pCur2->_pnext;
}
int diff = len1 - len2;
while (0 != diff)
{
if (diff > 0)
{
pHead1 = pHead1->_pnext;
diff--;
}
else
{
pHead2 = pHead2->_pnext;
diff++;
}
}
//到同一节点,距离交点有相同距离
while (pHead1 != pHead2)
{
pHead1 = pHead1->_pnext;
pHead2 = pHead2->_pnext;
}
return pHead1;
}
test.c
int main()
{
pNode Slist,p,P,T;
pNode pos;
SListInit(&Slist);
printf("初始化之后的链表为: ");
PrintList(&Slist);
SListPushBack(&Slist, 1);
SListPushBack(&Slist, 2);
SListPushBack(&Slist, 3);
SListPushBack(&Slist, 4);
SListPushBack(&Slist, 5);
SListPushBack(&Slist, 6);
printf("尾插之后的链表为:");
PrintList(&Slist);
pos = SListFind(&Slist, 3);
PrintSListFromTail(Slist);
printf("\n");
DeleteListNotTailNode(&Slist,pos);
PrintList(&Slist);
printf("中间节点:%d\n",FindMiddleNode(Slist)->_pdata);
printf("倒数第1个:%d\n", FindLastKNode(Slist, 1)->_pdata);
DeleteLastKNode(Slist, 1);
PrintList(&Slist);
SListPushBack(&Slist, 6);
SListPushBack(&Slist, 4);
SListPushBack(&Slist, 2);
SListPushBack(&Slist, 1);
PrintList(&Slist);
BubbleSort(Slist);
PrintList(&Slist);
SListInit(&Slist);
SListInit(&P);
SListInit(&T);
SListPushBack(&P, 3);
SListPushBack(&P, 4);
SListPushBack(&P, 5);
SListPushBack(&P, 7);
SListPushBack(&T, 1);
SListPushBack(&T, 2);
SListPushBack(&T, 6);
SListPushBack(&T, 8);
PrintList(&P);
PrintList(&T);
p = MergeSList(T, P);
printf("合并: \n");
PrintList(&p);
pos = ReverseSListOP(p);
PrintList(&pos);
ReverseSList(&pos);
PrintList(&pos);
//约瑟夫
pNode pTail = SListFind(&pos,8);
pTail->_pnext = pos;
int tmp = JosephCircle(&pos, 2);
printf("约瑟夫环最后返回值:%d\n",tmp);
system("pause");
return 0;
}