数据结构系列--循环链表( 三 )

<= pos)//链表不为空是合法的,长度正常,与单链表不同的是不需要posnext;}return ret;}//获取第pos个元素,将第pos个元素从链表里删除//特殊的删除第一个元素,除了将表头next移到第二个元素之外,还要将最后一个next移到第二个nextCircleListNode* CircleList_Delete(CircleList* list,int pos)//o(n){TCircleList* sList = (TCircleList*)list;//用到了数据封装,所以强制类型转换 CircleListNode* ret = NULL;//定义一个返回值int i = 0;if( (sList !=NULL) && (0 <= pos) )//链表不为空是合法的,长度正常{CircleListNode* current = (CircleListNode*)sList;CircleListNode* first = sList->header.next;// 标记第一个元素CircleListNode* last = (CircleListNode*)CircleList_Get(sList,sList->length - 1);// 由get函数得到最后一个元素for(i=0;inext;//第一个元素所在下标}ret = current->next;current->next = ret->next;sList->length--;if(first == ret)// 判断删除元素是否是原来表头,first指针与原来ret指针是否是同一个{sList->header.next = ret->next;// 将表头指向retlast->next = ret->next;// 指针移动到原来的第二个元素}if(slider->slider == ret)// SLIDER指向的元素和要删除的元素指针一致{sList->slider = ret->next ;// slider指向ret的下一个元素}if(sList->length == 0)// 如果链表空了则前面操作没有意义{sList->header.next = NULL;// 复原sList->slider = NULL;// 删除的元素刚好为链表最后一个元素,游标复原为空}}return ret;}// 获取当前游标指向的数据元素,删除对应的CircleListNode* node这个元素o(n0CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node){// 该做的检测正常做TCircleList* sList = (TCircleList*)list;//用到了数据封装,所以强制类型转换 CircleListNode* ret = NULL;//定义一个返回值int i = 0;if (sList != NULL){CircleListNode* current = (CircleListNode*)sList;// 做移动,查找node在循环链表的逻辑位置for(i=0;ilength;i++){if(current->next == node){ret =current->next;break;}current = current->next;}if(ret != NULL )// 找不到,非法元素{circleList_Delete(sList,i);// i就是所找到的删除位置,调用delete删除即可}}return ret;}CircleListNode* CircleList_Resert(CircleList* list)// o(1)将游标重置指向链表中的第一个元素{// 该做的检测正常做TCircleList* sList = (TCircleList*)list;//用到了数据封装,所以强制类型转换 CircleListNode* ret = NULL;//定义一个返回值if(sList != NULL ){slist->slider = sList->header.next;// slider重置到第一个元素ret = sList->slider ;// 返回判断重置是否成功}return ret;}CircleListNode* CircleList_Current(CircleList* list)//o(1)将游标移动指向到链表中的下一个数据元素{// 该做的检测正常做TCircleList* sList = (TCircleList*)list;//用到了数据封装,所以强制类型转换 CircleListNode* ret = NULL;//定义一个返回值if(sList != NULL ){ret = sList->slider ;}return ret;}CircleListNode* CircleList_Next(CircleList* list)//o(1)直接删除链表中的某个数据元素 {// 该做的检测正常做TCircleList* sList = (TCircleList*)list;//用到了数据封装,所以强制类型转换 CircleListNode* ret = NULL;//定义一个返回值// 当前游标指向下一个元素if((sList != NULL ) && (sList->slider != NULL )){ret = sList->slider ;// 在移动之前把当前值保存作为返回值返回sList->slider = ret->next;// 真正移动}return ret;}
循环链表的应用:约瑟夫问题
n个人围成一个圆圈,首先从第一个人从1开始报数,报到第m个人,令其出列;然后再从下一个人继续报数,报到第m个人,再另其出列……如此下去,求其出列顺序 。
main.c
#include #include #include"CircleList.h"//自己创建的文件,而不是系统文件用双引号struct Value{CircleListNode header;// 定义域int v;// 真正保存数据的域}int main(int argc,char *argv[]){int i = 0;CircleList*list = CircleList_Create();struct Value v1;struct Value v2;struct Value v3;struct Value v4;struct Value v5;struct Value v6;struct Value v7;struct Value v8;v1.v = 1 ;v2.v = 2 ;v3.v = 3 ;v4.v = 4 ;v5.v = 5 ;v6.v = 6 ;v7.v = 7 ;v8.v = 8 ;// 尾插法,插入到最后一个元素后面CircleList_Insert(list,( CircleListNode*)&V1, CircleList_Length(list));CircleList_Insert(list,( CircleListNode*)&V2, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V3, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V4, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V5,5);CircleList_Delete(list,0);// 证明是循环链表,删除第一个元素,循环两遍for(i=0;i