問題:
約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3…n分別表示)圍坐在一張圓桌周圍。從編號爲k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。通常解決這類問題時我們把編號從0~n-1,最後[1] 結果+1即爲原問題的解
問題分析
- 構建一個環(由鏈表來構建)最後一個的指針指向我們最開始的節點
- 環遍歷刪除問題
- 特別是剩下兩個元素時需要進行的操作
linkRing.h
#ifndef _LINK_RING_H_
#define _LINK_RING_H_
#include <assert.h>
#include <malloc.h>
#include <memory.h>
struct NodeT{
int data; //數據域
struct NodeT * next; //指針域
};
typedef struct NodeT * PNode;
typedef struct NodeT Node;
PNode createRing(int num); //創建環的個數
//void delNext(PNode pNode); //這個用不着,在遍歷刪除時已經進行了
int ring(PNode pNode,int num) ; //約瑟夫環的遍歷函數
#endif // _LINK_RING_H_
linkRing.c
#include "linkRing.h"
//創建環的個數
PNode createRing(int num)
{
PNode p,pNode;
int i = 0;
assert(num>0);
// pNode=(PNode)calloc(1,sizeof(Node));//分配內存空間
//pNode=(PNode)calloc(1,sizeof(Node));
for(i = 0;i<num;i++)
{
if(i == 0)
{
//頭節點的創建
pNode = p = (PNode)calloc(1,sizeof(Node));
}
else {
p->next = (PNode)calloc(1,sizeof(Node));
p = p->next;
}
p->data = i+1;
p->next = NULL;
}
p->next = pNode; //將這個數據形成一個環,鏈表的最後一個節點指向頭節點
return pNode;
}
//void delNext(PNode pNode)
//{
// PNode p = NULL;
// assert(pNode!=NULL);
// if(pNode->next == NULL)
// {
// printf("this node don't have next node");
// }
// else{
// p = pNode->next;
// pNode->next = p->next;
// free(p);
// p = NULL;
// }
//}
int ring(PNode pNode,int num) //第幾個出局
{
PNode p = NULL;
int i = 1;
assert(pNode!=NULL);
while(pNode->next != NULL)
{
if(i == num-1)
{
p = pNode->next;
if(p->next == pNode) //當只存在兩個數據時,pNode->next = p; p->next = pNode;刪除數據的方式
{
printf("current out num is:%d\n",p->data);
free(p);
pNode->next = NULL;
break;
}
else{
//其他刪除數據的方式
pNode->next = p->next;
printf("current out num is:%d\n",p->data);
free(p);
i = 0; //當前值爲pNode,沒有向後移動
p = NULL;
}
}
pNode = pNode->next;
i++;
}
return pNode->data;
}
測試的main
#include <stdio.h>
#include <stdlib.h>
#include "linkRing.h"
int main()
{
PNode pNode = NULL;
pNode = createRing(5);
printf("最終的結果是:%d",ring(pNode,3));
return 0;
}