#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("分配内存失败!\n");
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\n", 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\n", 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\n", 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\n", 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\n", ERRO_MSG);
return NULL;
}
//循环链表不可以做位置上限限制
if (pos<0)
{
ERRO_MSG = -2;
printf("没有该位置的元素! erro msg:%d\n", 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\n", ERRO_MSG);
return NULL;
}
TCircleList *tlist = (TCircleList *)list;
//定义尾节点
LinkNode * lastnode = NULL;
//循环链表不可以做位置上限限制
if (pos<0 || tlist->length<0)
{
ERRO_MSG = -2;
printf("没有该位置的元素! erro msg:%d\n", 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\n", 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\n", 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\n", 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\n", 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的值:\n");
//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!\n", tempstu->name, tempstu->age);
//在删除操作中 游标已经下移了
continue;
}
index++;
//游标下移
tempstu = (Student *)CircleList_Next(list);
//printf("当前元素的是%s,年龄是%d!\n", tempstu->name, tempstu->age);
}
//销毁循环链表
ret = CircleList_Destroy(&list);
}
void main(){
Test();
system("pause");
}