约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知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.cvoid 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;}