問題描述:
約瑟夫問題的一種描述是:編號爲1,2,……,n的n個人按順時針方向坐一圈,沒人持有一個密碼(正整數)。一開始任選一個作爲報數上限值m,從第一個開始順時針自1開始順序報數,報到m是停止報數。報m的人出列,將他的密碼作爲新的m值,從他在順時針方向的下一個人重新從1報數,如此下去,直到所有的人全部出列爲止。設計一個程序,求出出列順序
廢話不多說,上代碼:
/*==========Definition.h==============*/
/*標準庫函數*/
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#include<math.h>
#include<process.h>
/*常量定義*/
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define LIST_INIT_SIZE 5 /*循環鏈表存儲空間的初始分配量*/
/*類型定義*/
/*Status是函數的類型,其值是函數結果狀態代碼,如OK等*/
typedef int Status;
/*Boolean是布爾類型,其值是TRUE或FALSE*/
typedef int Boolean;
/*演示程序設定元素類型爲int,如有必要可以修改成其他類型*/
typedef int ElemType;
/*線性表的鏈式存儲結構*/
struct Node
{
ElemType data; /*數據域*/
struct Node * next; /*後繼指針域*/
ElemType bianhao;
};
typedef struct Node LinkNode;
typedef struct Node * LinkList;
/*=======循環鏈表功能模塊========*/
/*正序構造一個循環鏈表,並使用參數L返回*/
Status Initialize(LinkList&L,int n)
{
/*產生頭結點,並使L指向此頭結點。此語句等價於:L=(LinkList)malloc(sizeof(struct Node)); */
L=(LinkList)malloc(sizeof(LinkNode));
if(!L) /*存儲分配失敗*/
exit(OVERFLOW);
/*指針域暫時置爲空*/
L->next=NULL;
LinkList p,q;
q=L;
for(int i=0;i<n;i++)
{
/*生成新的有效數據結點*/
p=(LinkList)malloc(sizeof(LinkNode));
scanf("%d",&p->data);
p->bianhao=i+1;
/*該語句不能省,否則會造成程序異常*/
p->next=NULL;
q->next=p;
q=p;
}
q->next=L;
scanf("&d",L->data);
L->bianhao=n;
return OK;
}
/*=======在帶頭節點的循環鏈表L中,刪除第i個元素,並由e返回其值========*/
Status LinkDelet(LinkList&L, int i, ElemType &e,ElemType &n)
{
LinkList p=L;
int j = 0;
while (p->next&&j < i - 1) //查找到第i-1個節點
{
p = p->next;
++j;
}
LinkList q; //刪除第i個結點
q = p->next;
p->next = q ->next;
e = q->data;
n=q->bianhao;
free(q);
L=p;
return OK;
}
/*==================解決約瑟夫問題================*/
int main()
{
int mima,m,n,bianhao,num;
LinkList L;
printf("=====下面爲約瑟夫排序問題的計算過程及結果=====\n");
printf("請輸入環中元素的個數(正整數):");
scanf("%d",&n);
printf("請輸入%d個數據元素(每次輸入一個元素後空格,全部輸完以後回車):",n);
Initialize(L,n);
printf("請輸入上限值m:");
scanf(" %d",&m);
printf("出列順序爲:");
for(int i=0;i<n;i++)
{
LinkDelet(L,m,mima,bianhao);
m=mima;
printf(" %d",bianhao);
}
printf("\n");
return 0;
}
一開始,創建循環鏈表是把我難住了,雖然書上說的很簡單,但是一開始我的鏈表是帶頭結點的,而且並不打算在頭結點存值,所以把尾結點指向頭結點的下一個結點,循環起來難免出錯。於是最後只得妥協,先將尾結點的下一個結點指向頭結點,同時給頭結點賦值,這樣才輸出正確的結果。
運行結果