一:约瑟夫问题
- 约瑟夫问题-循环链表典型应用
- 例题:
n 个人围成一个圆圈,首先第 1 个人从 1 开始一个人一个人顺时针报数,报到第 m 个人,令其出列。然后再从下一 个人开始从 1 顺时针报数,报到第 m 个人,再令其出列,…,如此下去,求出列顺序。 - 假设:
m = 8,n=3
二:代码
1 main.c
/*
main.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CircleLinkList.h"
#define M 8
#define N 3
//创建数据结构体
typedef struct MYNUM{
CircleLinkNode node;
int val;
}My_Num;
//打印回调
void my_Print(CircleLinkNode*data){
My_Num *num=(My_Num*)data;
printf("%d ",num->val);
}
//比较回调
int my_Compare(CircleLinkNode*data1,CircleLinkNode*data2){
My_Num *num1=(My_Num*)data1;
My_Num *num2=(My_Num*)data2;
if(num1->val==num2->val){
return CIRCLELINKLIST_TRUE;
}
else{
return CIRCLELINKLIST_FALSE;
}
}
int main(void){
//初始化
CircleLinkList *clist=_Init_List();
//创建数据
My_Num num[M];
for(int i=0;i<M;i++){
num[i].val=i+1;
_Insert_List(clist,i,(CircleLinkNode*)&num[i]);//插入
}
//打印
_Print_List(clist,my_Print);
printf("\n ");
int index=1;
CircleLinkNode* Current_Node=clist->head.next;//辅助指针
while(_Size_List(clist)>1){
//有三个就输出
if(index==N){
//_Print_List(clist,my_Print);
My_Num *num=(My_Num*)Current_Node;
printf("%d ",num->val);
//将其释放
//按照值删除
CircleLinkNode* Current_Next=Current_Node->next;//缓存下一结点
_DeleteByValue_List(clist,Current_Node,my_Compare);
Current_Node= Current_Next;
//循环到头结点就跳过
if(Current_Node==&(clist->head)){
Current_Node=Current_Node->next;
}
index=1;
}
Current_Node=Current_Node->next;
//循环到头结点就跳过
if(Current_Node==&(clist->head)){
Current_Node=Current_Node->next;
}
index++;
}
if(_Size_List(clist)==1){
My_Num *num=(My_Num*)_Front_List(clist);
printf("%d ",num->val);
}
else{
printf("error!");
}
printf("\n");
//释放内存
_Free_List(clist);
return 0;
}
2 CircleLinkList.h
/*
CircleLinkList.h
实现机制为linux链表(企业链表)
*/
#ifndef _CIRCLELINKLIST_H_
#define _CIRCLELINKLIST_H_
#include <stdio.h>
#include <stdlib.h>
#define CIRCLELINKLIST_TRUE 1
#define CIRCLELINKLIST_FALSE 0
//创建小节点
typedef struct CIRCLELINKNODE{
struct CIRCLELINKNODE *next;
}CircleLinkNode;
//链表
typedef struct CIRCLELINKLIST{
CircleLinkNode head;//head头结点,是结构体
int size;//链表数据个数
}CircleLinkList;
//值删除回调函数
typedef int (*COMPARE)(CircleLinkNode *data1,CircleLinkNode *data2);
//打印回调函数
typedef void (*PRINT)(CircleLinkNode *data);
//初始化
CircleLinkList *_Init_List();
//插入
void _Insert_List(CircleLinkList *clist,int pos,CircleLinkNode *data);
//按照位置删除
void _DeleteByPos_List(CircleLinkList *clist,int pos);
//按照值删除
void _DeleteByValue_List(CircleLinkList *clist,CircleLinkNode *data,COMPARE my_Compare);
//返回第一个数据
CircleLinkNode *_Front_List(CircleLinkList *clist);
//获得链表长度
int _Size_List(CircleLinkList *clist);
//打印
void _Print_List(CircleLinkList *clist,PRINT my_Print);
//查找
int _Find_List(CircleLinkList *clist,CircleLinkNode *data,COMPARE my_Compare);
//释放内存
void _Free_List(CircleLinkList *clist);
#endif
3 CircleLinkList.c
/*
CircleLinkList.c
*/
#include "CircleLinkList.h"
//初始化
CircleLinkList *_Init_List(){
CircleLinkList *clist=(CircleLinkList *)malloc(sizeof(CircleLinkList));
clist->head.next=&(clist->head);
clist->size=0;
return clist;
}
//插入
void _Insert_List(CircleLinkList *clist,int pos,CircleLinkNode *data){
if(clist==NULL){
return ;
}
if(pos<0||pos>clist->size){
pos=clist->size;//默认往尾部插
}
CircleLinkNode *pCurrent=&(clist->head);
for(int i=0;i<pos;i++){//寻找前一结点
pCurrent=pCurrent->next;
}
//插入数据
data->next=pCurrent->next;
pCurrent->next=data;
clist->size++;
}
//打印
void _Print_List(CircleLinkList *clist,PRINT my_Print){
if(clist==NULL){
return ;
}
CircleLinkNode *pCurrent=(clist->head.next);
for(int i=0;i<clist->size;i++){
if(pCurrent==&(clist->head)){//如果打印多次,跳过头指针
pCurrent=pCurrent->next;
}
//打印
my_Print(pCurrent);
pCurrent=pCurrent->next;
}
}
//按照位置删除
void _DeleteByPos_List(CircleLinkList *clist,int pos){
if(clist==NULL){
return ;
}
if(pos<0||pos>=clist->size){
return ;
}
CircleLinkNode *pCurrent=&(clist->head);
for(int i=0;i<pos;i++){//寻找前一结点
pCurrent=pCurrent->next;
}
//将这个要删除结点缓存
CircleLinkNode *DelNode= pCurrent->next;
pCurrent->next=DelNode->next;
//释放删除结点空间,
/*
if(DelNode!=NULL){
free(DelNode);
DelNode=NULL;
}
*/
clist->size--;
}
//按照值删除
void _DeleteByValue_List(CircleLinkList *clist,CircleLinkNode *data,COMPARE my_Compare){
if(clist==NULL){
return ;
}
if(data==NULL){
return ;
}
CircleLinkNode *PreCurrent= &(clist->head);//数据的前一个
CircleLinkNode *pCurrent=PreCurrent->next;//查找到相对应的数据
for(int i=0;i<clist->size;i++){
if(my_Compare(pCurrent,data)==CIRCLELINKLIST_TRUE){//匹配成功
PreCurrent->next=pCurrent->next;
clist->size--;
break;
}
//没有匹配到
//PreCurrent->next= pCurrent;
//pCurrent->next=PreCurrent->next;
PreCurrent=pCurrent;
pCurrent=PreCurrent->next;
}
}
//返回第一个数据
CircleLinkNode *_Front_List(CircleLinkList *clist){
return clist->head.next;
}
//获得链表长度
int _Size_List(CircleLinkList *clist){
return clist->size;
}
//查找
int _Find_List(CircleLinkList *clist,CircleLinkNode *data,COMPARE my_Compare){
if(clist==NULL){
return -1;
}
if(data==NULL){
return -1;
}
CircleLinkNode *pCurrent=(clist->head.next);
int pos=-1;
for(int i=0;i<clist->size;i++){
if(my_Compare(pCurrent,data)==CIRCLELINKLIST_TRUE){//找到了
pos=i;
break;
}
pCurrent=pCurrent->next;
}
return pos;
}
//释放内存
void _Free_List(CircleLinkList *clist){
if(clist!=NULL){
free(clist);
clist=NULL;
}
}
3:结果显示
1.编译环境
centos 3.10.0-862.el7.x86_64
gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
2.编译命令
gcc main.c CircleLinkList.c -std=c99
./a.out
3.结果
1 2 3 4 5 6 7 8
3 6 1 5 2 8 4 7