单向循环链表与普通链表的区别在于:普通链表的最后一个链表的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;
}

[循环链表]——单向循环链表相关推荐

  1. 《恋上数据结构第1季》单向循环链表、双向循环链表以及约瑟夫环问题

    循环链表(CircleList) 链表的接口设计 单向循环链表 单向循环链表完整源码 双向循环链表 双向循环链表完整源码 双向循环链表解决约瑟夫环问题 如何发挥循环链表的最大威力? 静态链表 数据结构 ...

  2. python单向循环链表

    入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删. 目录 一.单向循环链表 二.建立节点对象 三.链表对象的初始定义 四.判断链表是否为空 五.获 ...

  3. node 获取表单数据 为空_数据结构与算法(python)单向循环链表

    单向循环链表 单链表的一个变形是单向循环链表, 链表的最后一个节点的next域不再为None, 而是指向链表的头节点. 单向循环链表如图所示: 单向循环链表 同样单向循环链表也是要使用python来对 ...

  4. python之链表、单链表、双向链表、单向循环链表

    python之链表.单链表.双向链表.单向循环链表 链表 顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时,又需要进行数据的搬迁,所以使用起来并非很灵活 链表结构可以充分利用计算机 ...

  5. 线性表—单向循环链表

    开始没看单向循环链表,感觉应该很简单,但实际上有几个概念不是很清楚: 头结点,头指针,尾指针,尾节点??? [个人理解]:头结点就是一个链表中实际存储数据的那个节点的前一个节点,这个节点不存储数据,只 ...

  6. 从无到有算法养成篇-单向循环链表的常规操作

    1.单向循环链表的创建 创建 tips: 由于存在两种情况: ① 第一次开始创建; ②已经创建,往里面新增数据 所以需要判断是否第一次创建链表 YES->创建一个新结点,并使得新结点的next ...

  7. Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...

  8. 算法—详细讲解单向循环链表的实现(python)

    单向循环列表如图所示 单向循环链表的实现 一.往链表头部添加一个节点值为4 1.新增一个节点node=Node(4) 新建一个节点 node=Node(data)if self.is_empty(): ...

  9. 数据结构-单向循环链表、双向循环链表、仿真链表

    一.单向循环链表: 1.概念: 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环. 和单链表相比,循环单链表的 ...

最新文章

  1. 你想要什么样的财富自由
  2. java file 如何关闭,java – 如何正确关闭从FileOutputStream获取的FileChannel
  3. Linux-LAMP-访问控制Directory
  4. js获取已知scripts中是否存在某变量_JS全局变量是如何工作的?
  5. Android:字节跳动必备Context原理解析及使用
  6. apache2.4配置虚拟主机
  7. React拾遗:Render Props及其使用场景
  8. 《大道至简》的幕后故事
  9. 【每日一练 088】性能优化-SQL tuning(一)
  10. 【java】Java实现异步调用方法(jdk1.8)
  11. 虚拟机安装python包会出问题吗_虚拟机CentOS7安装python3.6.2及requests模块的问题汇总...
  12. Linux中断函数堆栈,Linux在执行信号处理的过程中对堆栈的处理
  13. 计算机应用专业,报软考应该选什么?
  14. 表达式引擎Aviator基本介绍及使用以及基于Aviator的规则引擎(附代码详细介绍)
  15. [附源码]PHP计算机毕业设计老薛男生服装网(程序+LW)
  16. 无线传输时间同步 (基于NRF52设备)
  17. drools决策表的简单使用
  18. 三角形的几何公式大全_干货2020高中数学必备公式大全,吃透它们,数学再“捡”20分...
  19. markdown笔记(一)—— 首行缩进和换行
  20. 2022大学生就业指导答案——雷五明、雷辉等

热门文章

  1. web打印控件 LODOP的详细api
  2. 项目概要设计说明书 模板
  3. 【笔记】MATLAB中的图形(3)
  4. matlab画椭圆抛物面参数方程,椭圆抛物面 - calculus的日志 - 网易博客
  5. html制作毕业纪念,毕业纪念册制作
  6. hoj 1868 八数码(双广+hash)
  7. 网秦公布2016年第一季度财报 净营收为7350万美元
  8. 如何通过发新浪微博关闭电脑
  9. 实用盘点 十大mysql开发工具_细数十大你不得不用的MySQL开发工具
  10. linux挂载硬盘并建立samba共享操作流程