单向循环链表与普通链表的区别在于:普通链表的最后一个链表的next指向NULL,而单向循环链表的最后一个节点的next指向头结点
#ifndef CIRCLELINKLIST
#define CIRCLELINKLIST
#include
#include
#include
//链表小节点
typedef struct CIRCLELINKNODE {
struct CIRCLELINKNODE* next;
}CircleLinkNode;
//链表结构体
typedef struct CIRCLELINKLIST {
CircleLinkNode head;
int size;
}CircleLinkList;
//定义真假宏
#define CIRCLELINKLIST_TRUE 1
#define CIRCLELINKLIST_FALSE 0
//比较回调函数
typedef int(*COMPARENODE)(CircleLinkNode*, CircleLinkNode*);
//打印回调函数
typedef void(*PRINTNODE)(CircleLinkNode*);
//针对链表结构体操作的API函数
//链表初始化函数
CircleLinkList* initCircleLinkList();
//插入函数
void insertByPos(CircleLinkList* clist, int pos, CircleLinkNode* data);
//获得第一个元素
CircleLinkNode* getFront(CircleLinkList* clist);
//根据位置删除
void removeByPos(CircleLinkList* clist, int pos);
//根据值删除
void removeByValue(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare);
//获取链表长度
int getSize(CircleLinkList* clist);
//判断是否为空
int isEmpty(CircleLinkList* clist);
//根据值查找
int findByValue(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare);
//打印节点
void printList(CircleLinkList* clist, PRINTNODE print);
//释放内存
void freeSpace(CircleLinkList* clist);
#endif
#include "CircleLinkList.h"
//针对链表结构体操作的API函数
//链表初始化函数
CircleLinkList* initCircleLinkList() {
CircleLinkList* clist = (CircleLinkList*)malloc(sizeof(CircleLinkList));
//链表数据初始化
clist->head.next = &(clist->head);
clist->size = 0;
return clist;
}
//插入函数
void insertByPos(CircleLinkList* clist, int pos, CircleLinkNode* data) {
if (clist == NULL) {
return;
}
if (data == 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++;
}
//获得第一个元素
CircleLinkNode* getFront(CircleLinkList* clist) {
return clist->head.next;
}
//根据位置删除
void removeByPos(CircleLinkList* clist, int pos) {
if (clist == NULL) {
return;
}
if (pos < 0 || pos > clist->size) {
return;
}
CircleLinkNode* pCurrent = clist->head.next;
for (int i = 0; i < pos; i++) {
pCurrent = pCurrent->next;
}
//缓存当前节点的下一个节点
CircleLinkNode* pNext = pCurrent->next;
pCurrent->next = pNext->next;
clist->size--;
}
//根据值删除
void removeByValue(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare) {
if (clist == NULL || data == NULL) {
return;
}
CircleLinkNode* pPrev = &(clist->head);
CircleLinkNode* pCurrent = pPrev->next;
for (int i = 0; i < clist->size; i++) {
if (compare(pCurrent, data) == CIRCLELINKLIST_TRUE) {
pPrev->next = pCurrent->next;
clist->size--;
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
}
//获取链表长度
int getSize(CircleLinkList* clist) {
return clist->size;
}
//判断链表是否为空
int isEmpty(CircleLinkList* clist) {
if (clist->size == 0) {
return CIRCLELINKLIST_TRUE;
}
return CIRCLELINKLIST_FALSE; //返回0表示,非空
}
//根据值查找
int findByValue(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare) {
if (clist == NULL || data == NULL) {
return -1;
}
CircleLinkNode* pCurrent = clist->head.next;
int flag = -1;
for (int i = 0; i < clist->size; i++) {
if (compare(pCurrent, data) == CIRCLELINKLIST_TRUE) {
flag = i;
break;
}
pCurrent = pCurrent->next;
}
return flag;
}
//打印节点
void printList(CircleLinkList* clist, PRINTNODE print) {
if (clist == NULL) {
return;
}
CircleLinkNode* pCurrent = clist->head.next;
for (int i = 0; i < clist->size; i++) {
print(pCurrent);
pCurrent = pCurrent->next;
}
}
//释放内存
void freeSpace(CircleLinkList* clist) {
if (clist == NULL) {
return;
}
free(clist);
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include "CircleLinkList.h"
//测试结构体
typedef struct PERSON {
CircleLinkNode node; //连接各个数据
char name[64];
int age;
}Person;
void myPrint(CircleLinkNode * data) {
Person* person = (Person*)data;
printf("name:%s, age:%d\n", person->name, person->age);
}
//1代表相同,0代表不同
int myCompare(CircleLinkNode* data1, CircleLinkNode* data2) {
Person* p1 = (Person*)data1;
Person* p2 = (Person*)data2;
if (strcmp(p1->name, p2->name) == 0 && p1->age == p2->age) {
return CIRCLELINKLIST_TRUE;
}
return CIRCLELINKLIST_FALSE;
}
void test01() {
CircleLinkList* clist = initCircleLinkList();
//创建测试数据
Person p1, p2, p3, p4, p5, p6;
strcpy(p1.name, "aaa");
strcpy(p2.name, "bbb");
strcpy(p3.name, "ccc");
strcpy(p4.name, "ddd");
strcpy(p5.name, "eee");
strcpy(p6.name, "fff");
p1.age = 30;
p2.age = 40;
p3.age = 50;
p4.age = 60;
p5.age = 70;
p6.age = 80;
//插入数据到链表结构
insertByPos(clist, 0, (CircleLinkNode*)(&p1));
insertByPos(clist, 0, (CircleLinkNode*)(&p2));
insertByPos(clist, 0, (CircleLinkNode*)(&p3));
insertByPos(clist, 0, (CircleLinkNode*)(&p4));
insertByPos(clist, 0, (CircleLinkNode*)(&p5));
insertByPos(clist, 0, (CircleLinkNode*)(&p6));
//打印数据
printList(clist, myPrint);
printf("===============================\n");
//删除数据
removeByPos(clist, 2);
printList(clist, myPrint);
printf("===============================\n");
//查找数据
Person findP;
strcpy(findP.name, "ccc");
findP.age = 50;
int flag = findByValue(clist, &findP, myCompare);
if (flag == CIRCLELINKLIST_TRUE) {
printf("数据 %s 找到了\n", findP.name);
} else {
printf("数据 %s 未找到了\n", findP.name);
}
}
int main(void) {
test01();
system("pause");
return 0;
}
约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的,我们把问题描述如下:
- 现有M个人围成一桌坐下,编号从1到M,从编号为1的人开始报数。
- 报数也从1开始,报到N的人离席,从离席者的下一位在座成员开始,继续从1开始报数。
- 复现这个过程(各成员的离席次序),或者求最后一个在座的成员编号。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include "CircleLinkList.h"
//环内数据总数,N走一步出列
#define M 8
#define N 3
//存储的数据
typedef struct MYNUM {
CircleLinkNode node;
int val; //存储的数据编号
}MyNum;
//打印回调实现
void myPrint1(CircleLinkNode* data) {
MyNum* num = (MyNum*)data;
printf("%d ", num->val);
}
//比较回调打印
int myCompare1(CircleLinkNode* data1, CircleLinkNode* data2) {
MyNum* m1 = (MyNum*)data1;
MyNum* m2 = (MyNum*)data2;
if (m1->val == m2->val) {
return CIRCLELINKLIST_TRUE;
}
return CIRCLELINKLIST_FALSE;
}
void josephus() {
//创建循环链表
CircleLinkList* clist = initCircleLinkList();
//链表中插入数据
MyNum myNum[8]; //数据数组
for (int i = 0; i < 8; i++) {
myNum[i].val = i + 1;
insertByPos(clist, i, (CircleLinkNode*)&myNum[i]);
}
//打印环内数据
printList(clist, myPrint1);
printf("\n");
int index = 1; //表示当前位置
CircleLinkNode* pCurrent = clist->head.next;
while (getSize(clist) > 1) {
if (index == N) {
MyNum* tempNum = (MyNum*)pCurrent;
printf("%d ", tempNum->val);
//缓存待删除节点的下一个节点
CircleLinkNode* pNext = pCurrent->next;
//根据值删除
removeByValue(clist, pCurrent, myCompare1);
//判断是否是头结点,是的话需要跳过去
pCurrent = pNext;
if (pCurrent == &(clist->head)) {
pCurrent = pCurrent->next;
}
//重置index值
index = 1;
}
pCurrent = pCurrent->next;
if (pCurrent == &(clist->head)) {
pCurrent = pCurrent->next;
}
index++;
}
printf("\n");
if (getSize(clist) == 1) {
MyNum* font = (MyNum*)getFront(clist);
printf("最终筛选出的是 %d\n", font->val);
}
else {
printf("筛选出错!!!!\n");
}
//释放链表内存
freeSpace(clist);
}
int main(void) {
josephus();
return 0;
}