约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
算法原理:约瑟夫环运作如下:
1、一群人围在一起坐成[2] 环状(如:N)
2、从某个编号开始报数(如:K)
3、数到某个数(如:M)的时候,此人出列,下一个人重新报数
4、一直循环,直到所有人出列[3] ,约瑟夫环结束
void JosephCircle(PNode*pHead, size_tM); //约瑟夫环
void InsertNotHead(PNodepos, DataTypedata);// 在单链表非头结点前插入结点data
void PrintFromTail2Head(PNodepHead);// 使用递归实现从未到头打印单链表
void DeleteNotTailNode(PNodepos);// 删除单链表的非尾结点
PNode FindMidNode(PNodepHead);// 查找单链表的中间结点,要求只便利一次链表
PNode FindLastKNode(PNodepHead, size_tk);// 查找单链表的倒数第K个结点,要求只遍历一次链表
void BubbleSort(PNodepHead);// 使用冒泡排序对单链表进行排序
int IsListCross(PNodeL1, PNodeL2);// 判断两个单链表是否相交(链表不带环)
PNode GetCrossNode(PNodePL1, PNodePL2);// 若不带环的单链表相交,求交点
PNode ReverseList(PNode pHead);// 实现单链表的逆置:使用三个指针
void ReverseList_P(PNode* pHead);// 实现单链表的逆置:使用头插法
PNode MergeList(PNode pHead1, PNode pHead2);// 合并两个已序单链表,合并后依然有序
PNode HasCircle(PNode pHead);// 判断链表是否带环,若带环给出相遇点
size_t GetCircleLen(PNodepMeetNode);// 求环的长度
PNode GetEnterNode(PNode pHead, PNode pMeetNode);// 求环的入口点
int IsCrossWithCircle(PNode pHead1, PNode pHead2);// 判断链表是否相交,注意:链表可能带环
List.h
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
typedef int DataType;
typedef struct Node
{
DataType _data;
struct Node* _pNext;
}Node, *PNode;
void JosephCircle(PNode *pHead, size_t M); //约瑟夫环
void InsertNotHead(PNode pos, DataType data);// 在单链表非头结点前插入结点data
void PrintFromTail2Head(PNode pHead);// 使用递归实现从未到头打印单链表
void DeleteNotTailNode(PNode pos);// 删除单链表的非尾结点
PNode FindMidNode(PNode pHead);// 查找单链表的中间结点,要求只便利一次链表
PNode FindLastKNode(PNode pHead, size_t k);// 查找单链表的倒数第K个结点,要求只遍历一次链表
void BubbleSort(PNode pHead);// 使用冒泡排序对单链表进行排序
int IsListCross(PNode L1, PNode L2);// 判断两个单链表是否相交(链表不带环)
PNode GetCrossNode(PNode PL1, PNode PL2);// 若不带环的单链表相交,求交点
PNode ReverseList(PNode pHead);// 实现单链表的逆置:使用三个指针
void ReverseList_P(PNode* pHead);// 实现单链表的逆置:使用头插法
PNode MergeList(PNode pHead1, PNode pHead2);// 合并两个已序单链表,合并后依然有序
PNode HasCircle(PNode pHead);// 判断链表是否带环,若带环给出相遇点
size_t GetCircleLen(PNode pMeetNode);// 求环的长度
PNode GetEnterNode(PNode pHead, PNode pMeetNode);// 求环的入口点
int IsCrossWithCircle(PNode pHead1, PNode pHead2);// 判断链表是否相交,注意:链表可能带环
PNode Back(PNode pHead) // 返回单链表的最后一个结点的位置
{
if(pHead == NULL)
{
return NULL;
}
else
{
Node* PTailNode = pHead;
while(PTailNode->_pNext)
{
PTailNode = PTailNode->_pNext;
}
return PTailNode;
}
}
void JosephCircle(PNode *pHead, size_t M) //约瑟夫环
{
size_t m = 0;
PNode PCurNode = NULL;
PNode PTailNode = Back(*pHead);
PTailNode->_pNext = *pHead;
assert(pHead);
if(*pHead == NULL || M == 1)
{
return;
}
else
{
PNode PCurNode = *pHead;
while(PCurNode->_pNext != PCurNode)
{
PNode PDelNode = NULL;
m = M;
while(--m)
{
PCurNode = PCurNode->_pNext;
}
PDelNode = PCurNode->_pNext;
PCurNode->_data = PDelNode->_data;
PCurNode->_pNext = PDelNode->_pNext;
free(PDelNode);
*pHead = PCurNode;
}
PCurNode->_pNext = NULL;
}
}
void InsertNotHead(PNode pos, DataType data) // 在单链表非头结点前插入结点data
{
PNode PpreNode = NULL;
PNode PCurNode = NULL;
if(pos == NULL || pos->_pNext == NULL)
{
return;
}
PpreNode = BuyNode(pos->_data);
PpreNode->_pNext = pos->_pNext;
pos->_pNext = PpreNode;
pos->_data = data;
}
PNode FindMidNode(PNode pHead) // 查找单链表的中间结点,要求只便利一次链表
{
PNode pFast = NULL;
PNode pSlow = NULL;
PNode pre = NULL;
if(pHead == NULL || pHead->_pNext == NULL)
{
return NULL;
}
else
{
pFast = pHead;
pSlow = pHead;
while((NULL != pFast) && (NULL != pFast->_pNext))
{
pFast = pFast->_pNext->_pNext;
pre = pSlow;
pSlow = pSlow->_pNext;
}
pSlow->_pNext = NULL;
return pSlow; //偶数个的前一个中间节点
/*if(pFast == NULL)
{
pre->_pNext = NULL;
return pre;
}
if(pFast->_pNext == NULL)
{
pSlow->_pNext = NULL;
return pSlow; //偶数个的后一个中间节点
}*/
}
}
PNode FindLastKNode(PNode pHead, size_t k) // 查找单链表的倒数第K个结点,要求只遍历一次链表
{
assert(pHead);
if(k > Size(pHead))
{
return NULL;
}
else
{
PNode PreNode = pHead;
PNode PCurNode = pHead;
while(--k)
{
PreNode = PreNode->_pNext;
}
while(PreNode->_pNext)
{
PreNode = PreNode->_pNext;
PCurNode = PCurNode->_pNext;
}
PCurNode->_pNext = NULL;
return PCurNode;
}
}
void BubbleSort(PNode pHead) // 使用冒泡排序对单链表进行排序 //降序
{
if(pHead == NULL || pHead->_pNext == NULL)
{
return;
}
else
{
PNode pTailNode = NULL;
PNode PpreNode = pHead;
PNode PCurNode = PpreNode->_pNext;
while(PCurNode != pHead)
{
PpreNode = pHead;
PCurNode = PpreNode->_pNext;
while(PCurNode->_pNext != pTailNode)
{
if(PCurNode->_data > PpreNode->_data)
{
DataType tmp = PCurNode->_data;
PCurNode->_data = PpreNode->_data;
PpreNode->_data = tmp;
}
PpreNode = PpreNode->_pNext;
PCurNode = PCurNode->_pNext;
}
pTailNode = PCurNode;
PCurNode = PpreNode;
}
}
}
int IsListCross(PNode L1, PNode L2) // 判断两个单链表是否相交(链表不带环)
{
if(L1 == NULL || L2 == NULL)
{
return 0;
}
else
{
PNode pTailNode1 = L1;
PNode pTailNode2 = L2;
while(pTailNode1->_pNext)
{
pTailNode1 = pTailNode1->_pNext;
}
while(pTailNode2->_pNext)
{
pTailNode2 = pTailNode2->_pNext;
}
if(pTailNode2 == pTailNode1)
{
return 1;
}
else
{
return 0;
}
}
}
PNode GetCrossNode(PNode PL1, PNode PL2) // 若不带环的单链表相交,求交点
{
if(PL1 == NULL || PL2 == NULL)
{
return NULL;
}
else
{
if(!IsListCross(PL1, PL2))
{
return NULL;
}
else
{
size_t size1 = Size(PL1);
size_t size2 = Size(PL2);
int sz = size1 - size2;
PNode pPre1 = PL1;
PNode pPre2 = PL2;
if(sz<0)
{
pPre1 = PL1;
pPre2 = PL2;
sz = -sz;
while(sz--)
{
pPre2 = pPre2->_pNext;
}
}
else if(sz>0)
{
pPre1 = PL1;
pPre2 = PL2;
while(sz--)
{
pPre1 = pPre1->_pNext;
}
}
while(pPre1->_pNext)
{
if(pPre1 == pPre2)
{
pPre1->_pNext = NULL;
return pPre1;
}
pPre1 = pPre1->_pNext;
pPre2 = pPre2->_pNext;
}
if(pPre2 == pPre1)
{
pPre1->_pNext = NULL;
return pPre1;
}
else
{
return NULL;
}
}
}
}PNode ReverseList(PNode pHead)// 实现单链表的逆置:使用三个指针
{
PNode PreNode = NULL;
PNode PCurNode = NULL;
PNode PNextNode = NULL;
if(pHead == NULL || pHead->_pNext == NULL)
{
return NULL;
}
else
{
PreNode = pHead;
PCurNode = PreNode->_pNext;
PNextNode = PCurNode->_pNext;
while(PCurNode->_pNext)
{
PCurNode->_pNext = PreNode;
PreNode = PCurNode;
PCurNode = PNextNode;
PNextNode = PNextNode->_pNext;
}
PCurNode->_pNext = PreNode;
pHead->_pNext = NULL;
pHead = PCurNode;
return pHead;
}
}
// 实现单链表的逆置:使用头插法
void ReverseList_P(PNode* pHead)
{
PNode PNewNode = NULL;
PNode PreNode = NULL;
PNode PCurNode = NULL;
if(*pHead == NULL || (*pHead)->_pNext == NULL)
{
return;
}
PreNode = *pHead;
PCurNode = (*pHead)->_pNext;
while(PCurNode)
{
PreNode->_pNext = PNewNode;
PNewNode = PreNode;
PreNode = PCurNode;
PCurNode = PCurNode->_pNext;
}
PreNode->_pNext = PNewNode;
PNewNode = PreNode;
*pHead = PNewNode;
}
//合并两个已序单链表,合并后依然有序
PNode MergeList(PNode pHead1, PNode pHead2)
{
if(pHead1 == NULL && pHead2 == NULL)
{
return NULL;
}
else if(pHead1 == NULL || pHead2 == NULL)
{
if(pHead2 == NULL)
{
return pHead1;
}
else
{
return pHead2;
}
}
else
{
PNode pH1 = pHead1;
PNode pH2 = pHead2;
PNode PNewNode = NULL;
PNode TailNode = NULL;
if(pH1->_data <= pH2->_data)
{
PNewNode = pH1;
pH1 = pH1->_pNext;
}
else
{
PNewNode = pH2;
pH2 = pH2->_pNext;
}
TailNode = PNewNode;
while(pH1 && pH2)
{
if(pH1->_data <= pH2->_data)
{
PNewNode->_pNext = pH1;
pH1 = pH1->_pNext;
}
else
{
PNewNode->_pNext = pH2;
pH2 = pH2->_pNext;
}
PNewNode = PNewNode->_pNext;
}
if(pH1)
{
PNewNode->_pNext = pH1;
}
else
{
PNewNode->_pNext = pH2;
}
return TailNode;
}
}
// 判断链表是否带环,若带环给出相遇点
PNode HasCircle(PNode pHead)
{
if(pHead == NULL)
{
return NULL;
}
else
{
PNode pFast = pHead;
PNode pSlow = pHead;
{
while(pFast && pFast->_pNext)
{
pSlow = pSlow->_pNext;
pFast = pFast->_pNext->_pNext;
if(pFast == pSlow)
{
return pSlow;
}
}
return NULL;
}
}
}
// 求环的长度
size_t GetCircleLen(PNode pMeetNode)
{
PNode pCurNode = pMeetNode;
size_t count = 1;
while(pCurNode->_pNext != pMeetNode)
{
pCurNode = pCurNode->_pNext;
count++;
}
return count;
}
// 求环的入口点
PNode GetEnterNode(PNode pHead, PNode pMeetNode)
{
if(pHead == NULL)
{
return NULL;
}
else
{
PNode pFast = pHead;
PNode pSlow = pMeetNode;
{
while(pFast != pSlow)
{
pSlow = pSlow->_pNext;
pFast = pFast->_pNext;
}
return pSlow;
}
}
}
// 判断链表是否相交,注意:链表可能带环
int IsCrossWithCircle(PNode pHead1, PNode pHead2)
{
PNode pMeetNode1 = HasCircle(pHead1);
PNode pMeetNode2 = HasCircle(pHead2);
if(pHead1 == NULL || pHead2 == NULL)
{
return 0;
}
else if(pMeetNode1 == NULL && pMeetNode2 == NULL)
{
PNode pTailNode1 = pHead1;
PNode pTailNode2 = pHead2;
while(pTailNode1->_pNext)
{
pTailNode1 = pTailNode1->_pNext;
}
while(pTailNode2->_pNext)
{
pTailNode2 = pTailNode2->_pNext;
}
if(pTailNode2 == pTailNode1)
{
return 1;
}
else
{
return 0;
}
}
else if(pMeetNode1 && pMeetNode2)
{
PNode pCurNode = pMeetNode1;
while(pCurNode->_pNext != pMeetNode1)
{
if(pCurNode == pMeetNode2)
{
return 2;
}
pCurNode = pCurNode->_pNext;
}
return 0;
}
else
{
return 0;
}
}
test.c
void Test6()
{
Node *Node = NULL;
InitList(&Node);
PushBack(&Node, 1);
PushBack(&Node, 2);
PushBack(&Node, 3);
PushBack(&Node, 4);
PushBack(&Node, 5);
PushBack(&Node, 6);
PushBack(&Node, 7);
PrintList(Node);
JosephCircle(&Node, 3);
PrintList(Node);
}
void Test7()
{
Node *Node = NULL;
InitList(&Node);
PushBack(&Node, 1);
PushBack(&Node, 2);
PushBack(&Node, 3);
PushBack(&Node, 4);
PushBack(&Node, 5);
PushBack(&Node, 6);
PushBack(&Node, 7);
PrintList(Node);
PrintFromTail2Head(Node);
PrintList(Node);
InsertNotHead(Find(Node, 5),8);
PrintList(Node);
}
void Test8()
{
Node *Node = NULL;
InitList(&Node);
PushBack(&Node, 1);
PushBack(&Node, 2);
PushBack(&Node, 3);
PushBack(&Node, 4);
PushBack(&Node, 5);
PushBack(&Node, 6);
PushBack(&Node, 7);
PrintList(Node);
DeleteNotTailNode(Find(Node,4));
PrintList(Node);
}
void Test9()
{
Node *Node = NULL;
InitList(&Node);
PushBack(&Node, 1);
PushBack(&Node, 2);
PushBack(&Node, 3);
PushBack(&Node, 4);
PushBack(&Node, 5);
PushBack(&Node, 6);
//PushBack(&Node, 7);
PrintList(Node);
PrintList(FindMidNode(Node));
PrintList(FindLastKNode(Node, 3));
}
void Test10()
{
Node *Node = NULL;
InitList(&Node);
PushBack(&Node, 6);
PushBack(&Node, 2);
PushBack(&Node, 3);
PushBack(&Node, 7);
PushBack(&Node, 5);
PushBack(&Node, 1);
PrintList(Node);
BubbleSort(Node);
PrintList(Node);
}
void Test11()
{
Node *Node1 = NULL;
Node *Node2 = NULL;
Node *TailNode = NULL;
int ret = 0;
InitList(&Node1);
InitList(&Node2);
PushBack(&Node1, 1);
PushBack(&Node1, 2);
PushBack(&Node1, 3);
PushBack(&Node1, 4);
PushBack(&Node1, 5);
PushBack(&Node1, 6);
PushBack(&Node2, 4);
PushBack(&Node2, 5);
TailNode = Back(Node2);
TailNode->_pNext = Find(Node1, 2);
ret = IsListCross(Node1, Node2);
printf("%d\n", ret);
TailNode = GetCrossNode(Node1, Node2);
PrintList(TailNode);
}void Test12()
{
Node *Node = NULL;
InitList(&Node);
PushBack(&Node, 1);
PushBack(&Node, 2);
PushBack(&Node, 3);
PushBack(&Node, 4);
PushBack(&Node, 5);
PushBack(&Node, 6);
PrintList(Node);
ReverseList_P(&Node);
PrintList(Node);
}
void Test13()
{
Node *Node1 = NULL;
Node *Node2 = NULL;
Node *NewNode = NULL;
InitList(&Node1);
InitList(&Node2);
PushBack(&Node1, 1);
PushBack(&Node1, 1);
PushBack(&Node1, 3);
PushBack(&Node1, 4);
PushBack(&Node1, 4);
PushBack(&Node1, 6);
PushBack(&Node2, 2);
PushBack(&Node2, 2);
PushBack(&Node2, 3);
PushBack(&Node2, 4);
PushBack(&Node2, 5);
PushBack(&Node2, 5);
NewNode = MergeList(Node1, Node2);
PrintList(NewNode);
}
void Test14()
{
Node *Node1 = NULL;
Node *Node2 = NULL;
Node *TailNode = NULL;
size_t ret = 0;
InitList(&Node1);
InitList(&Node2);
PushBack(&Node1, 1);
PushBack(&Node1, 2);
PushBack(&Node1, 3);
PushBack(&Node1, 4);
PushBack(&Node1, 5);
PushBack(&Node1, 6);
TailNode = Back(Node1);
TailNode->_pNext = Find(Node1, 2);
ret = GetCircleLen(HasCircle(Node1));
TailNode = GetEnterNode(Node1, HasCircle(Node1));
TailNode->_pNext = NULL;
PrintList(TailNode);
}
void Test15()
{
Node *Node1 = NULL;
Node *Node2 = NULL;
Node *TailNode1 = NULL;
Node *TailNode2 = NULL;
size_t ret = 0;
InitList(&Node1);
InitList(&Node2);
PushBack(&Node1, 1);
PushBack(&Node1, 2);
PushBack(&Node1, 3);
PushBack(&Node1, 4);
PushBack(&Node1, 5);
PushBack(&Node1, 6);
PushBack(&Node2, 0);
PushBack(&Node2, 7);
PushBack(&Node2, 9);
PushBack(&Node2, 8);
TailNode1 = Back(Node1);
TailNode1->_pNext = Find(Node1, 4);
TailNode2 = Back(Node2);
TailNode2->_pNext = Find(Node1, 3);
ret = IsCrossWithCircle(Node1, Node2);
if(ret == 0)
{
printf("这两个链表不相交\n");
}
if(ret == 1)
{
printf("这两个不带环链表相交\n");
}
if(ret == 2)
{
printf("这两个带环链表相交\n");
}
}
int main(){Test11();system("pause");return 0;}