#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"文件中,应该包含了上述步骤的具体实现,通过阅读和分析代码,我们可以深入理解Josephus问题的C++单循环链表解决方案。这个实现不仅满足了课本上的习题要求,也展示了如何将理论知识应用于实践。...
该算法使用链表数据结构来存储元素,并使用循环链表来实现Josephus问题的解决方案。 链表数据结构 在该算法中,我们使用了两个结构体:`struct node`和`struct list`。`struct node`表示链表中的每个节点,包含了...
在解决Josephus问题时,我们可以创建一个循环单链表,链表的节点代表参与游戏的人。初始时,链表的长度为N,每个节点代表一个参与者,节点中存储着该人的编号。接着,我们从第一个节点开始,每报数M次就将当前节点...
Josephus约瑟夫问题的循环链表实现.cpp
《Josephus问题与链表法实现》 Josephus问题,源于古罗马时期的历史事件,是一个经典的理论计算问题。在数学和计算机科学中,它被用来探讨各种淘汰算法。问题的基本设定是:N个人围成一个圈,从某人开始按顺时针...
VC++2012编程演练数据结构《2》单循环链表与约瑟夫问题
Josephus问题可以描述为如下的一个游戏:N个人编号从1到N,围坐成一个圆圈,从1号开始传递一个热土豆,经过M次传递后拿着土豆的人离开圈子,由坐在离开的人的后面的人拿起热土豆继续进行游戏,直到圈子只剩下最后一...
总之,Josephus问题的单循环链表解决方案巧妙地结合了链表的特性和循环结构,为这一经典问题提供了一种直观且易于理解的编程实现。在实际编程挑战中,这种思路可以帮助我们解决许多涉及数据结构和算法的问题。
7. **递归解决方案**:虽然这里提到的是使用单循环链表,但约瑟夫问题也可以用递归方式解决,通过模拟每个节点的生存情况,直到只剩下一个节点。 8. **优化策略**:对于大规模的数据,可以考虑使用更高效的数据结构...
在计算机科学领域,约瑟夫环(Josephus Problem)是一个著名的理论问题,它涉及到了循环链表和数据结构的操作。本程序以C/C++语言实现,利用带头结点的单向循环链表来解决这个问题。这里我们将深入探讨相关知识点。 ...
《约瑟夫环问题的C语言实现》 约瑟夫环问题是一个经典的计算机科学问题,源于古罗马数学家约瑟夫提出的一个设想。...这种编程方法展示了数据结构和算法在解决问题中的重要作用,是学习计算机科学的基础之一。
题目要求使用C语言编程实现约瑟夫环问题,并通过单向循环链表来管理参与游戏的人。以下是具体的知识点解析: #### 知识点解析 ##### 1. 单向循环链表 单向循环链表是一种特殊的线性表存储结构,其中每个节点包含...
本项目专注于使用C语言实现循环链表,并将其应用于解决著名的约瑟夫问题。 约瑟夫问题(Josephus Problem)源于一个古老的故事,它涉及到在圆形排列的人群中,按照一定的间隔(通常为3或4)剔除一个人,直到剩下...
总的来说,约瑟夫环问题与循环链表的结合,为我们提供了一个理解链表操作和解决问题的实用案例。它不仅展示了链表数据结构的灵活性,也让我们看到了算法设计的巧妙之处。通过深入研究这个问题,不仅可以提升编程技能...
这个问题可以使用数据结构来解决,特别是循环链表。 在【单向循环链表】中,每个节点包含数据(如人的编号和密码)以及指向下一个节点的指针。循环链表没有头节点,最后一个节点的指针会指向第一个节点,形成一个...
《使用单循环链表解决约瑟夫环问题》 约瑟夫环问题,作为一个经典的计算机科学问题,其核心在于模拟一种淘汰机制。...通过这种方式,我们可以有效地求解出圈顺序,同时也展示了数据结构在解决问题中的重要作用。
在VC++中,我们可以利用单向循环链表来解决这个问题,因为链表结构非常适合模拟环形结构。 首先,我们需要定义一个链表节点结构。在C++中,这通常通过创建一个结构体或类来完成,包含一个整型数据成员存储报数值,...
单向循环链表是一种常见的数据结构,用于存储一系列有序或无序的数据元素。在这个场景中,我们关注的是如何使用这种数据结构来实现约瑟夫环(Josephus Problem)的经典算法。约瑟夫环问题是一个理论上的问题,源自古...
在计算机科学中,循环链表被广泛应用于各种算法和数据结构的设计,其中一个著名的应用就是约瑟夫环问题。 约瑟夫环问题是一个经典的理论问题,源于古罗马时期的传说。假设有一群人围成一个圈,从某个人开始报数,每...
通过以上内容,我们了解了Josephus问题及其C语言实现,包括链表结构、问题解决算法以及可能的查找操作。这个经典的理论问题不仅锻炼了我们的编程技巧,还加深了对数据结构和算法的理解。在实际编程中,类似这样的...