1. 程式人生 > >約瑟夫環 C語言 單循環鏈表

約瑟夫環 C語言 單循環鏈表

node 前驅 輸入 truct sizeof -- 描述 reat 約瑟夫

/*---------約瑟夫環---------*/  
/*---------問題描述---------*/  
/*編號為1,2,…,n的n個人圍坐一圈,每人持一個密碼(正整數)。 
一開始任選一個正整數作為報數上限值m, 
從第一個人開始自1開始順序報數,報到m時停止。 
報m的人出列,將他的密碼作為新的m值,從他的下一個人開始重新從1報數, 
如此下去,直至所有人全部出列為止。試設計一個程序求出列順序。*/  
  
/*---------問題分析---------*/  
/*n個人圍坐一圈,且不斷有人出列,即頻繁刪除,應用單循環鏈表。 
有因為報數的過程是計數的過程,每個數據結點計1,因此不帶頭結點合適。 
又因為第一次報數的上限是任選的正整數,有可能報到第一個人時出列,為刪除第一個結點, 
須知其前驅結點的位置,即尾結點的位置,因此應設尾指針,不設頭指針*/  
  
#include<stdio.h>  
#include<stdlib.h>  
  
typedef struct lnode{  
    int num;    //序號  
    int key;    //密碼  
    struct lnode *next;  
}LNode,*LinkList;  
  
void CreatList(LinkList &L)  
{//建立含有n個結點的不帶頭結點的單循環鏈表,L為尾指針  
    int n;  
    int i;  
    LinkList s,p;  
    printf("請輸入人數:");  
    scanf("%d",&n);  
    while(n<=0)  
    {  
        printf("人數太少!請重新輸入:");  
        scanf("%d",&n);  
    }  
    L=(LinkList)malloc(sizeof(LNode));  //建立第一個結點,輸入第一個人的信息  
    L->num=1;  
    printf("請輸入第1個人的密碼:");  
    scanf("%d",&L->key);  
    p=L;//p指向目前鏈表的尾結點,之後新建結點均插入表尾  
    for(i=2;i<=n;i++)  
    {  
        s=(LinkList)malloc(sizeof(LNode));  
        s->num=i;  
        printf("請輸入第%d個人的密碼:",i);  
        scanf("%d",&s->key);  
        p->next=s;   //將新結點*s插入鏈表尾部,p指向新結點  
        p=s;  
    }  
    p->next=L;   //尾結點的next指向表首結點,構成循環鏈表  
    L=p;        //L指向尾結點,即鏈表為設尾指針的鏈表  
}  
  
void Joseph(LinkList &L)  
{  
      
    int key,i;  
    LinkList p,q;  
    printf("請輸入正整數:");  
    scanf("%d",&key);  
    p=L;  
    while(p->next!=p)  
    {  
        for(i=1;i<key;i++)  
        {  
            p=p->next;  
        }  
        q=p->next;  
        printf("%d ",p->num);  
        p->next=q->next;  
        key=q->key;  
        free(q);   
    }  
    printf("%d ",p->num);  
}  
  
int main()  
{  
    LinkList L;  
    printf("-----------------------------約瑟夫環-----------------------------\n");  
      
    CreatList(L);  
    Joseph(L);  
}  

  

約瑟夫環 C語言 單循環鏈表