#ifndef _vzhangcirclelist #define _vzhangcirclelist typedef struct _LinkNode{ struct _LinkNode *pnext; }LinkNode; typedef void CircleList; //创建线性循环链表 _declspec(dllexport) CircleList* CircleList_Create(); //销毁线性循环链表 _declspec(dllexport) int CircleList_Destroy(CircleList** list); //清空线性循环链表 _declspec(dllexport) int CircleList_Clear(CircleList* list); //获取线性循环链表长度 _declspec(dllexport) int CircleList_Length(CircleList* list); //线性链表指定位置插入元素 _declspec(dllexport) int CircleList_Insert(CircleList* list, LinkNode* node, int pos); //获取线性循环链表指定位置的元素 _declspec(dllexport) LinkNode* CircleList_Get(CircleList* list, int pos); //删除线性循环链表指定位置的元素 _declspec(dllexport) LinkNode* CircleList_Delete(CircleList* list, int pos); //add //删除当前节点 _declspec(dllexport) LinkNode* CircleList_DeleteNode(CircleList* list, LinkNode* node); //游标重置 _declspec(dllexport) LinkNode* CircleList_Reset(CircleList* list); //获取当前游标节点 _declspec(dllexport) LinkNode* CircleList_Current(CircleList* list); //获取下一个元素节点 _declspec(dllexport) LinkNode* CircleList_Next(CircleList* list); #endif
//线性循环链表代码实现 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"circlelist.h" //定义循环链表结构体 typedef struct _TCircleList{ //定义一个头结点 LinkNode node; //定义链表长度 int length; //定义游标 LinkNode *slider; }TCircleList; //创建线性循环链表 _declspec(dllexport) CircleList* CircleList_Create(){ //分配链表结构体内存 TCircleList * tlist = (TCircleList *)malloc(sizeof(TCircleList)); if (tlist==NULL) { printf("分配内存失败! "); return NULL; } tlist->node.pnext = NULL; tlist->length = 0; tlist->slider = NULL; return tlist; } //销毁线性循环链表 _declspec(dllexport) int CircleList_Destroy(CircleList** list){ int ERRO_MSG = 0; if (list==NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return ERRO_MSG; } TCircleList *tlist = (TCircleList *)*list; if (tlist!=NULL) { free(tlist); tlist = NULL; } *list = NULL; return ERRO_MSG; } //清空线性循环链表 _declspec(dllexport) int CircleList_Clear(CircleList* list){ int ERRO_MSG = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return ERRO_MSG; } TCircleList *tlist = (TCircleList *)list; tlist->node.pnext = NULL; tlist->length = 0; return ERRO_MSG; } //获取线性循环链表长度 _declspec(dllexport) int CircleList_Length(CircleList* list){ int ERRO_MSG = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return ERRO_MSG; } TCircleList *tlist = (TCircleList *)list; return tlist->length; } //线性链表指定位置插入元素 _declspec(dllexport) int CircleList_Insert(CircleList* list, LinkNode* node, int pos){ int ERRO_MSG = 0, i = 0; if (list == NULL || node==NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return ERRO_MSG; } TCircleList *tlist = (TCircleList *)list; //判断插入的位置 if (pos<0 || pos>tlist->length) { //进行容错处理 pos = tlist->length; } //此时current指向头结点 //假设在0个位置插入 LinkNode * current = &tlist->node; for (i = 0; i < pos && (current->pnext!=NULL); i++) { current = current->pnext; } node->pnext = current->pnext; current->pnext = node; //元素个数+1 tlist->length++; /* 元素个数必须先加1 不然获取最后一个节点的数据不正确 lastnode的数据不正确 */ //闭合链表 /* 对于在尾部插入,上面算法就可以实现闭合 因为最后一个节点的pnext就指向第0个元素 对于在第0个位置插入 那么就必须让尾部的pnext指向新插入的元素 */ if (tlist->node.pnext == node) { //如果插入节点的地址 等于 头结点的pnext的地址 //获取尾部节点 //注意 获取最后一个节点是 tlist->length-1 LinkNode * lastnode = CircleList_Get(list, tlist->length-1); lastnode->pnext = node; } //为游标赋值 tlist->slider = node; return ERRO_MSG; } //获取线性循环链表指定位置的元素 _declspec(dllexport) LinkNode* CircleList_Get(CircleList* list, int pos){ int ERRO_MSG = 0, i = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return NULL; } //循环链表不可以做位置上限限制 if (pos<0) { ERRO_MSG = -2; printf("没有该位置的元素! erro msg:%d ", ERRO_MSG); return NULL; } TCircleList *tlist = (TCircleList *)list; //此时current指向第0个节点 LinkNode * current = tlist->node.pnext; LinkNode * ret = NULL; for (i = 0; i < pos; i++) { current = current->pnext; } ret = current; return ret; } //删除线性循环链表指定位置的元素 _declspec(dllexport) LinkNode* CircleList_Delete(CircleList* list, int pos){ int ERRO_MSG = 0, i = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return NULL; } TCircleList *tlist = (TCircleList *)list; //定义尾节点 LinkNode * lastnode = NULL; //循环链表不可以做位置上限限制 if (pos<0 || tlist->length<0) { ERRO_MSG = -2; printf("没有该位置的元素! erro msg:%d ", ERRO_MSG); return NULL; } //此时current指向头结点 LinkNode * current = &tlist->node; LinkNode * ret = NULL; for (i = 0; i < pos; i++) { current = current->pnext; } //找到指定位置的上一个节点 ret = current->pnext; //判断删除的是不是第0个节点 if (ret == tlist->node.pnext) { //获取循环链表尾节点 lastnode = CircleList_Get(list, tlist->length - 1); } current->pnext = ret->pnext; //元素个数-1 tlist->length--; //如果最后的节点不是NULL 尾节点指向第0个节点 /* 强调: 这个操作对于链表只有一个元素的情况下是错误的 所以后面会对链表只有一个元素特别处理 */ if (lastnode!=NULL) { /*lastnode->pnext = tlist->node.pnext;*/ /* 以上代码错误 循环链表 头结点的node属性也必须发生变化 */ lastnode->pnext = ret->pnext; tlist->node.pnext = ret->pnext; } //如果游标正好是被删除的元素 后移一个元素 //游标处理 /* 强调: 这个操作对于链表只有一个元素的情况下是错误的 所以后面会对链表只有一个元素特别处理 */ if (tlist->slider == ret) { tlist->slider = ret->pnext; } //如果链表元素个数为0 全部置空 ---对链表只有一个元素特别处理 /* 注意:这个条件必须放在最后 因为假设只有一个元素的时候 lastnode其实最后指向的是被删除的元素 此时lastnode也是不为空的 循环链表很特殊 */ if (tlist->length == 0) { tlist->node.pnext = NULL; tlist->slider = NULL; } return ret; } //删除当前节点 _declspec(dllexport) LinkNode* CircleList_DeleteNode(CircleList* list, LinkNode* node){ int ERRO_MSG = 0, i = 0; if (list == NULL || node==NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return NULL; } TCircleList *tlist = (TCircleList *)list; //此时current指向头结点 LinkNode * current = tlist->node.pnext; for (i = 0; i < tlist->length; i++) { //比较2元素的地址是否相等 //单向链表只能通过上一个元素找到下一个 所以这里使用pPrior if (current == node) { break; } current = current->pnext; } //调用删除节点的函数(删除逻辑太复杂 不适合在这里写) return CircleList_Delete(list, i); } //游标重置 _declspec(dllexport) LinkNode* CircleList_Reset(CircleList* list){ int ERRO_MSG = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return NULL; } TCircleList *tlist = (TCircleList *)list; tlist->slider = tlist->node.pnext; return tlist->slider; } //获取当前游标节点 _declspec(dllexport) LinkNode* CircleList_Current(CircleList* list){ int ERRO_MSG = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return NULL; } TCircleList *tlist = (TCircleList *)list; return tlist->slider; } //获取下一个元素节点 _declspec(dllexport) LinkNode* CircleList_Next(CircleList* list){ int ERRO_MSG = 0; if (list == NULL) { ERRO_MSG = -1; printf("传入参数不可以为空! erro msg:%d ", ERRO_MSG); return NULL; } TCircleList *tlist = (TCircleList *)list; tlist->slider = tlist->slider->pnext; return tlist->slider; }
//线性循环链表--约瑟夫问题 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> #include"circlelist.h" /* 约瑟夫环(约瑟夫问题) 是一个数学的应用问题: 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。 从编号为k的人开始报数, 数到m的那个人出列; 他的下一个人又从1开始报数, 数到m的那个人又出列; 依此规律重复下去,直到圆桌周围的人全部出列 */ typedef struct _Student{ //必须加一个LinkNode节点 LinkNode node; char name[30]; int age; }Student; void Test(){ Student s1, s2, s3, s4, s5, s6, s7, s8; Student * tempstu=NULL; int numx = 3, i = 0, ret = 0,index=0,j=0; //printf("请输入m的值: "); //scanf("%d", &numx); strcpy(s1.name, "小米"); s1.age = 1; strcpy(s2.name, "小刚"); s2.age = 2; strcpy(s3.name, "小红"); s3.age = 3; strcpy(s4.name, "啸天"); s4.age = 4; strcpy(s5.name, "莲华"); s5.age = 5; strcpy(s6.name, "夏利"); s6.age = 6; strcpy(s7.name, "小李"); s7.age = 7; strcpy(s8.name, "阿凯"); s8.age = 8; //线性循环链表指针 CircleList *list = NULL; //创建线性循环链表 list = CircleList_Create(); //插入元素 CircleList_Insert(list, (LinkNode *)&s1, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s2, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s3, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s4, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s5, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s6, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s7, CircleList_Length(list)); CircleList_Insert(list, (LinkNode *)&s8, CircleList_Length(list)); //重置游标 tempstu = (Student *)CircleList_Reset(list); while (CircleList_Length(list) > 1){ if (index == numx-1){ index = 0; //删除当前元素 tempstu = (Student *)CircleList_DeleteNode(list, (LinkNode*)tempstu); printf("被删除的是%s,年龄是%d! ", tempstu->name, tempstu->age); //在删除操作中 游标已经下移了 continue; } index++; //游标下移 tempstu = (Student *)CircleList_Next(list); //printf("当前元素的是%s,年龄是%d! ", tempstu->name, tempstu->age); } //销毁循环链表 ret = CircleList_Destroy(&list); } void main(){ Test(); system("pause"); }