用循环链表编程实现约瑟夫问题,n个人围成一圈,从某人开始报数1,2,.., m,数到m的人出圈,然后从出圈的下一个人(m+1)开始重复此过程,直到全部人出圈,于是得到一个出圈人员的新序列,如当n=8,m=4时,若从第一个位置数起,则所得到的新的序列为4,8,5,2,1,3,7,6。
//约瑟环问题
void josepho(LoopLink *l,int k){
if(NULL==l || list_empty(l) || k<0 ){
printf("所给链表不合法或所给数太小,无法解决问题\n");
return;
}
int n=l->len; //循环次数,n个人循环n次
LoopLink *p=list_kill_head(l); //对链表进行去头操作
l=NULL;
LoopLink *q; //定义指针,用来标记删除的结点
for(int i=0;i<n;i++){
for(int j=1;j<k-1;j++){
p=p->next;
}
q=p->next;
printf("%d\t",q->data);
p->next=q->next;
free(q);
}
putchar(10);
}
运行结果:
主函数代码:
#include <stdio.h>
#include "looplist.h"
int main(int argc, const char *argv[])
{
//创建
LoopLink *l=list_create();
if(NULL==l){
printf("创建失败\n");
return 0;
}
//头插
list_insert_head(l,1);
list_insert_head(l,3);
list_insert_head(l,5);
list_insert_head(l,7);
list_insert_head(l,9);
list_display(l);
//约瑟环问题
josepho(l,3);
return 0;
}
定义函数代码:
#include <stdio.h>
#include <stdlib.h>
#include "looplist.h"
//创建
LoopLink *list_create(){
LoopLink *l=(LoopLink *)malloc(sizeof(LoopLink));
if(NULL==l){
printf("创建失败\n");
return NULL;
}
//初始化
l->len=0;
l->next=l;//将指针指向自己
printf("创建成功\n");
return l;
}
//判空
int list_empty(LoopLink *l){
return l->next==l;
}
//头插
int list_insert_head(LoopLink *l,datatype e){
if(NULL==l){
printf("所给链表不合法\n");
return 0;
}
//申请结点封装数据
LoopLink *p=(LoopLink *)malloc(sizeof(LoopLink));
if(NULL==p){
printf("结点申请失败\n");
return 0;
}
p->data=e;
p->next=NULL;
//头插
p->next=l->next;
l->next=p;
l->len++;
printf("插入成功\n");
return 1;
}
//遍历
void list_display(LoopLink *l){
if(NULL==l || list_empty(l)){
printf("遍历失败\n");
return;
}
LoopLink *q=l->next;
while(q!=l){
printf("%d\t",q->data);
q=q->next;
}
putchar(10);
}
//头删
int list_delete_head(LoopLink *l){
if(NULL==l || list_empty(l)){
printf("删除失败\n");
return 0;
}
LoopLink *q=l->next;
l->next=q->next;
free(q);
q=NULL;
l->len--;
printf("删除成功\n");
return 1;
}
//删除头结点
LoopLink *list_kill_head(LoopLink *l){
if(NULL==l || list_empty(l)){
printf("去头失败\n");
return 0;
}
//定义遍历指针指向最后一个结点
LoopLink *q=l->next;
while(q->next!=l){
q=q->next;
}
q->next=l->next;
free(l);
l=NULL;
printf("去头成功\n");
return q->next;
}
//删除头结点后的遍历
void list_display_noh(LoopLink *h){
if(NULL==h){
printf("遍历失败\n");
return;
}
LoopLink *q=h;
do{
printf("%d\t",q->data);
q=q->next;
}while(q != h);
putchar(10);
}
//约瑟环问题
void josepho(LoopLink *l,int k){
if(NULL==l || list_empty(l) || k<0 ){
printf("所给链表不合法或所给数太小,无法解决问题\n");
return;
}
int n=l->len; //循环次数,n个人循环n次
LoopLink *p=list_kill_head(l); //对链表进行去头操作
l=NULL;
LoopLink *q; //定义指针,用来标记删除的结点
for(int i=0;i<n;i++){
for(int j=1;j<k-1;j++){
p=p->next;
}
q=p->next;
printf("%d\t",q->data);
p->next=q->next;
free(q);
}
putchar(10);
}
头文件:
#ifndef __LOOPLIST_H__
#define __LOOPLIST_H__
typedef int datatype;
typedef struct Node
{
union{
int len; //头结点数据域
datatype data; //普通节点数据域
};
struct Node *next; //指针域
}LoopLink;
//创建
LoopLink *list_create();
//判空
int list_empty(LoopLink *l);
//头插
int list_insert_head(LoopLink *l,datatype e);
//遍历
void list_display(LoopLink *l);
//头删
int list_delete_head(LoopLink *l);
//删除头结点
LoopLink *list_kill_head(LoopLink *l);
//删除头结点后的遍历
void list_display_noh(LoopLink *h);
//约瑟环问题
void josepho(LoopLink *l,int k);
#endif
Makefile:
TARGET:=a.out
OBJS:=looplist.o main.o
CC:=gcc
CFLAGS:=-o
CFLAGSs:=-c -o
$(TARGET):$(OBJS)
$(CC) $(OBJS) $(CFLAGS) $(TARGET)
%.o:%.c
$(CC) $*.c $(CFLAGSs) $*.o
.PHONY:clean
clean:
rm *.o a.out