#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;
}
#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;
}