数据结构一:链表(约瑟夫问题)

一:约瑟夫问题

  • 约瑟夫问题-循环链表典型应用

  • 例题:
    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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐维康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值