`
anna_zr
  • 浏览: 200531 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

循环链表解决Josephus问题

 
阅读更多
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#define CL_SUCCESS    0
#define CL_NO_MEM     1
#define CL_EMPTY      2
#define CL_ZERO_SIZE  3

typedef struct CL_ITEM{
int Tag;
struct CL_ITEM *Prev, *Next;
void *Object;
size_t Size;
}CL_ITEM;

typedef struct CLIST{
CL_ITEM *CurrentItem;
size_t   NumItems;
}CLIST;
//创建结点
CL_ITEM *CLCreate(int Tag, void *Object, size_t Size){
CL_ITEM *NewItem;
if(Size > 0){
  NewItem = (CL_ITEM *)malloc(sizeof *NewItem);
  if(NewItem != NULL){
   NewItem->Prev = NewItem->Next = NULL;
   NewItem->Tag = Tag;
   NewItem->Size = Size;
   NewItem->Object = (void*)malloc(Size);
   if(NewItem->Object == NULL){
    free(NewItem);
    NewItem = NULL;
   }else{
    memcpy(NewItem->Object, Object, Size);
   }
  }
}
return NewItem;
}
//向循环链表List中添加新元素
int CLAddItem(CLIST *List, int Tag, void *Object, size_t Size){
CL_ITEM *NewItem;
int Result = CL_SUCCESS;
assert(List != NULL);
//为新结点分配需要的内存空间
NewItem = CLCreate(Tag, Object, Size);
if(NewItem == NULL){
  Result = CL_NO_MEM;
}else{
  ++List->NumItems;
  //List empty
  if(List->CurrentItem == NULL){
   List->CurrentItem = NewItem;
   List->CurrentItem->Next = NewItem;
   List->CurrentItem->Prev = NewItem;
  }else{
   NewItem->Prev                 = List->CurrentItem->Prev;
   NewItem->Next                 = List->CurrentItem;
   List->CurrentItem->Prev->Next = NewItem;
   List->CurrentItem->Prev       = NewItem;
  }
}
return Result;
}
//更新循环链表指定结点的值
int CLUpdate(CLIST *List,int NewTag,void *NewObject,size_t NewSize){
int Result = CL_SUCCESS;
void *p;

assert(List != NULL);
if(NewSize > 0){
  //is empty?
  if(List->NumItems > 0){
   //重新分配空间
   p = realloc(List->CurrentItem->Object, NewSize);
   if(NULL != p){
    List->CurrentItem->Object = p;
    memmove(List->CurrentItem->Object, NewObject, NewSize);
    List->CurrentItem->Tag    = NewTag;
    List->CurrentItem->Size   = NewSize;
   }else{
    Result = CL_NO_MEM;
   }
  }else{
   Result = CL_EMPTY;
  }
}else{
  Result = CL_ZERO_SIZE;
}
return Result;
}
//得到链表中指定元素的值
void *CLGetData(CLIST *List,int *Tag,size_t *Size){
void *p = NULL;
assert(List != NULL);

if(List->CurrentItem != NULL){
  if(Tag != NULL){
   *Tag = List->CurrentItem->Tag;
  }
  if(Size != NULL){
   *Size = List->CurrentItem->Size;
  }
  p = List->CurrentItem->Object;
}
return p;
}
//旋转表
void CLRotate(CLIST *List, int Places){
int Multiple;
int i;
assert(List != NULL);
//判断表是否为空表
if(List->NumItems > 0){
  if(Places < 0){
   Multiple = (List->NumItems - 1 - Places) / List->NumItems;
   Places += Multiple * List->NumItems;
  }
  Places %= List->NumItems;
  //倒序转
  if(Places > (int)List->NumItems / 2){
   Places = List->NumItems - Places;
   for(i = 0; i < Places; i++){
    List->CurrentItem = List->CurrentItem->Prev;
   }
  }else{
   //顺序转
   for(i = 0; i < Places; i++){
    List->CurrentItem = List->CurrentItem->Next;
   }
  }
}
}
//删除循环链表中的结点
int CLDelete(CLIST *List){
int Deleted = 0;
CL_ITEM *PrevItem, *NextItem, *ThisItem;
assert(List != NULL);

if(List->NumItems > 0){
  Deleted = 1;

  ThisItem = List->CurrentItem;
  free(ThisItem->Object);
  NextItem = ThisItem->Next;
  PrevItem = ThisItem->Prev;
  //如果循环链表中只存在一个元素,将表置为空表
  if(1 == List->NumItems){
   List->CurrentItem = NULL;
  }else{
   //把结点从循环链表中摘掉
   List->CurrentItem = NextItem;
   NextItem->Prev = PrevItem;
   PrevItem->Next = NextItem;
  }
  //释放
  free(ThisItem);
  //结点个数-1;
  --List->NumItems;
}
return Deleted;
}
//清空循环链表
void CLDestroy(CLIST *List){
assert(List != NULL);
while(CLDelete(List)){
  continue;
}
}
//访问循环链表
int CLWalk(CLIST *List,int(*Func)(int, void *, void *),void *Args){
CL_ITEM *ThisItem;
int i, Result = 0;
assert(List != NULL);

for(ThisItem = List->CurrentItem, i = 0;!Result && i < (int)List->NumItems;ThisItem = ThisItem->Next, i++){
  Result = (*Func)(ThisItem->Tag,ThisItem->Object,Args);
}
return Result;
}
//以下测试程序来自C语言教科书,用于解决Josephus问题.
int _tmain(int argc, _TCHAR* argv[])
{
char *Intro[] = {
  "This Josephus Problem",
  "---------------------",
  " ",
  "Consider a ring of N items. If the Kth item",
  "is eliminated, there will now be N-1 items.",
  "If this procedure is performed iteratively",
  "eventually there will be just one item",
  "remaining. Which is it?",
  " ",
  "This program provides the answer.",
  " ",
  NULL
};
char **Text;
char buffer[32];
char *endp;
CLIST Circle = {0};
int Result = EXIT_SUCCESS;
unsigned long N, K, i;
for(Text = Intro; *Text != NULL; ++Text){
  puts(*Text);
}

puts(" \nHow many items in the ring?");
if(fgets(buffer, sizeof buffer, stdin) == NULL){
  puts("Program aborted .");
  exit(EXIT_SUCCESS);
}
N = strtoul(buffer, &endp, 10);
if(buffer == endp || N == 0){
  puts("Program aborted.");
  Result = EXIT_FAILURE;
}else{
  puts("Count how many items before removing one?");
  if(fgets(buffer, sizeof buffer, stdin) == NULL){
   puts("Program aborted.");
   exit(EXIT_FAILURE);
  }
  K = strtoul(buffer, &endp, 10);
  if(buffer == endp || K == 0){
   puts("Program aborted.");
   exit(EXIT_FAILURE);
  }
}

for(i = 0; Result == EXIT_SUCCESS && i < N; i++){
  if(CLAddItem(&Circle, 0, &i, sizeof i) != CL_SUCCESS){
   printf("Insufficient memory. Sorry. \n");
   Result = EXIT_FAILURE;
  }
}

if(Result == EXIT_SUCCESS){
  while(Circle.NumItems > 1){
   CLRotate(&Circle, K);
   printf("Removing item %lu. \n", *(unsigned long *)CLGetData(&Circle, NULL, NULL));

   CLDelete(&Circle);

   CLRotate(&Circle, -1);
  }
  printf("The last item is %lu .\n", *(unsigned long*)CLGetData(&Circle, NULL, NULL));
}


CLDestroy(&Circle);

return Result;
}

分享到:
评论

相关推荐

    Josephus问题C++单循环链表实现

    在提供的"Josephus"文件中,应该包含了上述步骤的具体实现,通过阅读和分析代码,我们可以深入理解Josephus问题的C++单循环链表解决方案。这个实现不仅满足了课本上的习题要求,也展示了如何将理论知识应用于实践。...

    Josephus问题C语言单循环链表.doc

    该算法使用链表数据结构来存储元素,并使用循环链表来实现Josephus问题的解决方案。 链表数据结构 在该算法中,我们使用了两个结构体:`struct node`和`struct list`。`struct node`表示链表中的每个节点,包含了...

    用循环单链表解决josephus问题的算法.rar_循环单链表

    在解决Josephus问题时,我们可以创建一个循环单链表,链表的节点代表参与游戏的人。初始时,链表的长度为N,每个节点代表一个参与者,节点中存储着该人的编号。接着,我们从第一个节点开始,每报数M次就将当前节点...

    Josephus约瑟夫问题的循环链表实现.cpp

    Josephus约瑟夫问题的循环链表实现.cpp

    josephus(链表法)

    《Josephus问题与链表法实现》 Josephus问题,源于古罗马时期的历史事件,是一个经典的理论计算问题。在数学和计算机科学中,它被用来探讨各种淘汰算法。问题的基本设定是:N个人围成一个圈,从某人开始按顺时针...

    VC++2012编程演练数据结构《2》单循环链表与约瑟夫问题

    VC++2012编程演练数据结构《2》单循环链表与约瑟夫问题

    单向和双向循环链表实例(Josephus环问题)

    Josephus问题可以描述为如下的一个游戏:N个人编号从1到N,围坐成一个圆圈,从1号开始传递一个热土豆,经过M次传递后拿着土豆的人离开圈子,由坐在离开的人的后面的人拿起热土豆继续进行游戏,直到圈子只剩下最后一...

    Josephe问题的解答,利用单循环链表

    总之,Josephus问题的单循环链表解决方案巧妙地结合了链表的特性和循环结构,为这一经典问题提供了一种直观且易于理解的编程实现。在实际编程挑战中,这种思路可以帮助我们解决许多涉及数据结构和算法的问题。

    用C++做的单循环链表简单表示约瑟夫问题

    7. **递归解决方案**:虽然这里提到的是使用单循环链表,但约瑟夫问题也可以用递归方式解决,通过模拟每个节点的生存情况,直到只剩下一个节点。 8. **优化策略**:对于大规模的数据,可以考虑使用更高效的数据结构...

    C/C++经典约瑟夫环问题——带头结点的单向循环链表

    在计算机科学领域,约瑟夫环(Josephus Problem)是一个著名的理论问题,它涉及到了循环链表和数据结构的操作。本程序以C/C++语言实现,利用带头结点的单向循环链表来解决这个问题。这里我们将深入探讨相关知识点。 ...

    用链表表示循环链表的约瑟夫环的问题的源代码

    《约瑟夫环问题的C语言实现》 约瑟夫环问题是一个经典的计算机科学问题,源于古罗马数学家约瑟夫提出的一个设想。...这种编程方法展示了数据结构和算法在解决问题中的重要作用,是学习计算机科学的基础之一。

    约瑟夫环单循环链表C语言实现

    题目要求使用C语言编程实现约瑟夫环问题,并通过单向循环链表来管理参与游戏的人。以下是具体的知识点解析: #### 知识点解析 ##### 1. 单向循环链表 单向循环链表是一种特殊的线性表存储结构,其中每个节点包含...

    链表-使用C语言实现循环链表应用之解决约瑟夫问题.zip

    本项目专注于使用C语言实现循环链表,并将其应用于解决著名的约瑟夫问题。 约瑟夫问题(Josephus Problem)源于一个古老的故事,它涉及到在圆形排列的人群中,按照一定的间隔(通常为3或4)剔除一个人,直到剩下...

    约瑟夫环,循环链表,循环链表

    总的来说,约瑟夫环问题与循环链表的结合,为我们提供了一个理解链表操作和解决问题的实用案例。它不仅展示了链表数据结构的灵活性,也让我们看到了算法设计的巧妙之处。通过深入研究这个问题,不仅可以提升编程技能...

    利用单向循环链表存储结构模拟约瑟夫问题,按照出列的顺序印出每个人的编号。

    这个问题可以使用数据结构来解决,特别是循环链表。 在【单向循环链表】中,每个节点包含数据(如人的编号和密码)以及指向下一个节点的指针。循环链表没有头节点,最后一个节点的指针会指向第一个节点,形成一个...

    用单循环链表实现约瑟夫环问题

    《使用单循环链表解决约瑟夫环问题》 约瑟夫环问题,作为一个经典的计算机科学问题,其核心在于模拟一种淘汰机制。...通过这种方式,我们可以有效地求解出圈顺序,同时也展示了数据结构在解决问题中的重要作用。

    VC++采用单向循环链表实现约瑟夫环

    在VC++中,我们可以利用单向循环链表来解决这个问题,因为链表结构非常适合模拟环形结构。 首先,我们需要定义一个链表节点结构。在C++中,这通常通过创建一个结构体或类来完成,包含一个整型数据成员存储报数值,...

    单向循环链表实现约瑟夫环.zip

    单向循环链表是一种常见的数据结构,用于存储一系列有序或无序的数据元素。在这个场景中,我们关注的是如何使用这种数据结构来实现约瑟夫环(Josephus Problem)的经典算法。约瑟夫环问题是一个理论上的问题,源自古...

    循环链表实现约瑟夫环

    在计算机科学中,循环链表被广泛应用于各种算法和数据结构的设计,其中一个著名的应用就是约瑟夫环问题。 约瑟夫环问题是一个经典的理论问题,源于古罗马时期的传说。假设有一群人围成一个圈,从某个人开始报数,每...

    Josephus 问题的 C 语言代码

    通过以上内容,我们了解了Josephus问题及其C语言实现,包括链表结构、问题解决算法以及可能的查找操作。这个经典的理论问题不仅锻炼了我们的编程技巧,还加深了对数据结构和算法的理解。在实际编程中,类似这样的...

Global site tag (gtag.js) - Google Analytics