黑马练习之循环链表解决约瑟夫问题

黑马数据结构笔记之使用循环链表解决约瑟夫问题

1 思想:一个人从1依次喊一个数,喊到指定数时,该人退出队伍,下一个人重新从1开始喊。

代码实现:
1)头文件:

#ifndef CIRCLELIST_H
#define CIRCLELIST_H

//挂钩结构体
typedef struct CSNode{
	struct CSNode *next;
}CircleSNode;

//管理链表结构体
typedef struct CList{
	CircleSNode head;
	int size;
}CircleList;

//查找回调函数
typedef int (*MYCOMPAER)(CircleSNode *c1,CircleSNode *c2);
//打印回调函数
typedef void (*PRINT)(CircleSNode *c);

//链表初始化
CircleList *Init_CircleList();
//插入链表
int Insert_CircleList(CircleList *clist,int pos,CircleSNode *data);
//删除 -根据位置
int DelByPos_CircleList(CircleList *clist,int pos);
//删除 -根据值
int DelByValue_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp);
//查找
int Find_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp);
//打印
int Print_CircleList(CircleList *clist,PRINT print);
//获取第一个元素
CircleSNode *GetFront_CircleList(CircleList *clist);
//返回链表大小
int GetSize_CircleList(CircleList *clist);
//销毁内存
int Destory_CircleList(CircleList *clist);
#endif

2).cpp文件:

#include"CircleList.h"
#include<stdio.h>
#include<stdlib.h>

//链表初始化
CircleList *Init_CircleList(){

	CircleList *clist=(CircleList*)malloc(sizeof(CircleList));
	clist->head.next=&(clist->head); //使链表尾部指向头结点--循环
	clist->size=0;

	return clist;

}
//插入链表
int Insert_CircleList(CircleList *clist,int pos,CircleSNode *data){

	if(clist==NULL){
		return -1;
	}
	//数据为空也没必要插入
	if(data==NULL){
		return -1;
	}
	if(pos<0 || pos>clist->size){
		pos=clist->size;
	}
	    //插入
	//先找到要插入前一节点
	CircleSNode *pPre=&(clist->head);
	for(int i=0;i<pos;i++){
		pPre=pPre->next;
	}
	//开始插入
	data->next=pPre->next;
	pPre->next=data;

	clist->size++;

	return 0;

}
//删除 -根据位置
int DelByPos_CircleList(CircleList *clist,int pos){

	if(clist==NULL){
		return -1;
	}
	if(pos<0||pos>=clist->size){
		printf("输入下标有误,数组越界了!\n");
		return -1;
	}
	    //删除
	//找到要删除点的前一节点
	CircleSNode *pPre=&(clist->head);
	for(int i=0;i<pos;i++){
		pPre=pPre->next;
	}
	//开始删除
	pPre->next=pPre->next->next;

	clist->size--;

	return 0;
}
//删除 -根据值
int DelByValue_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp){

	if(clist==NULL){
		return -1;
	}
	if(data==NULL){
		return -1;
	}
/*  while删除
	int i=0;
	CircleSNode *pPre=&(clist->head);
	CircleSNode *pCur=clist->head.next;
	while(pCur!=&(clist->head)){
		if(comp(pCur,data)){
			break;
		}
		pPre=pCur;
		pCur=pCur->next;
		i++;
	}
	//如果找到i肯定会少加一次1
	if(i==clist->size){
		printf("没有找到可删除的值\n");
		return -1;
	}
	//开始删除
	pPre->next=pCur->next;
*/
	//for删除
	CircleSNode *pPre=&(clist->head);
	CircleSNode *pCur=clist->head.next;
	for(int i=0;i<clist->size;i++){
		if(comp(pCur,data)){
			break;
		}
		pPre=pCur;
		pCur=pCur->next;
	}

	//开始删除
	pPre->next=pCur->next;

	clist->size--;

	return 0;

}
//查找
int Find_CircleList(CircleList *clist,CircleSNode *data,MYCOMPAER comp){
	if(clist==NULL){
		return -1;
	}
	if(data==NULL){
		return -1;
	}
	int i=0;
	CircleSNode *pCur=clist->head.next;
	while(pCur!=&(clist->head)){
		if(comp(pCur,data)){
			break;
		}
		pCur=pCur->next;
		i++;
	}
	//如果找到i肯定会少加一次1
	if(i==clist->size){
		printf("没有找到可删除的值\n");
		return -1;
	}

	return i;
}
//打印
int Print_CircleList(CircleList *clist,PRINT print)  {

	if(clist==NULL){
		return -1;
	}
/*
	CircleSNode *pCur=clist->head.next;
	while(pCur!=&(clist->head)){

		print(pCur);
		pCur=pCur->next;
	}
*/
	CircleSNode *pCur=clist->head.next;
	for(int i=0;i<clist->size;i++){
		//多次打印,在打印之前,跳过头结点
		if(pCur==&(clist->head)){
			pCur=pCur->next;
		}
		print(pCur);
		pCur=pCur->next;
	}
	return 0;
}
//获取第一个元素
CircleSNode *GetFront_CircleList(CircleList *clist){
	return clist->head.next;
}
//返回链表大小
int GetSize_CircleList(CircleList *clist){
	return clist->size;
}
//销毁内存
int Destory_CircleList(CircleList *clist){

	if(clist==NULL){
		return -1;
	}
	free(clist);

	return 0;
}

3)主函数测试:

#include"CircleList.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define M 8
#define N 3

//自定义类型
typedef struct Num{
	CircleSNode node;  //每个自定义类型都使用挂钩串联
	int num;
}MyNum;

//打印回调函数
void MyPrint(CircleSNode *cs){
	MyNum *p=(MyNum *)cs;
	printf("%2d",p->num);
	
}

//比较回调函数
int MyCompare(CircleSNode *cs1,CircleSNode *cs2){
	MyNum *p1=(MyNum *)cs1;
	MyNum *p2=(MyNum *)cs2;
	if(p1->num==p2->num){
		return 1;
	}
	return 0;
}

void test01(){

	//创建链表
	CircleList *clist=Init_CircleList();

	//创建数据
	MyNum m[M];
	for(int i=0;i<M;i++){
		m[i].num=i+1;
		Insert_CircleList(clist,i,(CircleSNode*)&m[i]); //不是插入m数组,而是对象
	}
	//打印
	Print_CircleList(clist,MyPrint);
	printf("\n");

	//约瑟夫重点开始
	//循环按规律不断删除
	int count=1;     //记录那个人喊的数,用于判断是否与规定的数相等然后删除    并非是下标 
	CircleSNode *pCur=clist->head.next;
	while(clist->size>1){
		if(count==N){
			//可以先输出看看,但要先转有数据的类型
			MyNum *tmp=(MyNum*)pCur;
			printf("%2d",tmp->num);

			//按值删除
			//删除前保存下一节点
			CircleSNode *pNext=pCur->next;
			DelByValue_CircleList(clist,pCur,MyCompare);
			//clist->size--; 不需要自行写,调用函数做了

			pCur=pNext;
			//若是头结点,则指向下一节点
			if(pCur==&(clist->head)){
				pCur=pCur->next;
			}
			count=1;     //不用continue跳出是因为1肯定不等于N,所以让他执行下面,继续往后跳
			
		}
		//依旧要判断是否为头结点
		pCur=pCur->next;
		if(pCur==&(clist->head)){
			pCur=pCur->next;
		}
		count++;
	}

	if(clist->size==1){
		MyNum *tmp=(MyNum*)GetFront_CircleList(clist);
		printf("\n");
		printf("%d\n",tmp->num);
	}else{
		printf("程序出错\n");
	}


	//销毁内存
	Destory_CircleList(clist);

}

int main(){

	test01();

	return 0;
}
发布了54 篇原创文章 · 获赞 1 · 访问量 712

猜你喜欢

转载自blog.csdn.net/weixin_44517656/article/details/105291064