单向循环链表与普通链表的区别在于:普通链表的最后一个链表的next指向NULL,而单向循环链表的最后一个节点的next指向头结点

 头文件:
#ifndef CIRCLELINKLIST #define CIRCLELINKLIST #include <stdio.h> #include
<stdlib.h> #include <string.h> //链表小节点 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
API实现:
#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 <stdio.h> #include <stdlib.h>
#include <string.h> #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
<stdio.h> #include <stdlib.h> #include <string.h> #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; }

技术
©2019-2020 Toolsou All rights reserved,
TypeScript:函数类型接口8道大厂指针笔试题让你秒杀指针!!!MySQL 日期时间加减mysql 查询条件之外的数据_mysql 查询符合条件的数据查linux的操作系统版本,如何查看Linux操作系统版本?将String类型转换成Map数据类型使用uuid做MySQL主键,被老板,爆怼一顿C语言中的字符串函数和字符函数linux服务器中毒排查--基础篇C# ASCII码字符转换