1.标准的循环链表与一般链表多了个游标,多了3个游标操作函数。
2.循环链表API的写法与一般链表大致一样,只有0号节点的增加和删除需要注意,还有一次节点的插入和最后一个节点的删除需要注意,删除时游标的移动需要注意。
3.循环链表相对于一般链表并无多大性能上的增强,只是让链表解决约瑟夫问题十分方便。
下面给出代码:
(代码看似复杂,只需要需要配合画图分析就可理解)
CircleList.h #ifndef __CIRCLELIST_H__ #define __CIRCLELIST_H__ typedef void CircleList; typedef struct CircleListNode{ struct CircleListNode *next; }CircleListNode; //与一般链表相同的API CircleList* CircleList_Create(); void CircleList_Destory(CircleList *list); int CircleList_Length(CircleList *list); void CircleList_Clear(CircleList *list); int CircleList_Insert(CircleList *list, CircleListNode *node, int pos); CircleListNode* CircleList_Delete(CircleList *list, int pos); CircleListNode* CircleList_Get(CircleList *list, int pos); //因为游标增加的API CircleListNode* CircleList_DeleteNode(CircleList *list, CircleListNode *node); CircleListNode* CircleList_Reset(CircleList *list); CircleListNode* CircleList_Current(CircleList *list); CircleListNode* CircleList_Next(CircleList *list); #endif
CircleList.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "CircleList.h" typedef struct _tag_CircleList{ CircleListNode header; int length; CircleListNode *slider; }TCircleList; CircleList* CircleList_Create() { TCircleList *tlist; tlist = (TCircleList *)malloc(sizeof(TCircleList)); if(NULL == tlist) { printf("CircleList_Create err (NULL == tlist)\n"); return NULL; } memset(tlist, 0, sizeof(TCircleList)); return tlist; } void CircleList_Destory(CircleList *list) { TCircleList *tlist; if(NULL == list) { printf("CircleList_Destory err (NULL == list)\n"); return; } tlist = (TCircleList *)list; free(tlist); tlist = NULL; return ; } int CircleList_Length(CircleList *list) { TCircleList *tlist; if(NULL == list) { printf("CircleList_Length err (NULL == list)\n"); return -1; } tlist = (TCircleList *)list; return tlist->length; } void CircleList_Clear(CircleList *list) { TCircleList *tlist; if(NULL == list) { printf("CircleList_Clear err (NULL == list)\n"); return; } tlist = (TCircleList *)list; memset(tlist, 0, sizeof(TCircleList)); return ; } int CircleList_Insert(CircleList *list, CircleListNode *node, int pos) { TCircleList *tlist; CircleListNode *current, *last; int i; if(NULL == list || NULL == node || pos < 0) { printf("CircleList_Insert err (NULL == list || NULL == node || pos < 0)\n"); return -1; } tlist = (TCircleList *)list; if(pos > tlist->length) pos = tlist->length; current = &tlist->header; for(i = 0; i < pos; i++) current = current->next; node->next = current->next; current->next = node; tlist->length++; if(&tlist->header == current) { last = CircleList_Get(list, tlist->length - 1); last->next = node; } if(node->next == node) tlist->slider = node; return 0; } CircleListNode* CircleList_Delete(CircleList *list, int pos) { TCircleList *tlist; CircleListNode *current, *last = NULL, *node; int i; if(NULL == list || pos < 0) { printf("CircleList_Delete err (NULL == list || pos < 0)\n"); return NULL; } tlist = (TCircleList *)list; if(pos >= tlist->length) pos = tlist->length -1; current = &tlist->header; for(i = 0; i < pos; i++) current = current->next; node = current->next; //如果删除的是0号节点,那么提前布局找到last节点 if(current == &tlist->header) last = CircleList_Get(list, tlist->length -1); current->next = node->next; tlist->length--; if(tlist->slider == node) tlist->slider = node->next; if(last != NULL) { last->next = current->next; } //链表只有一个节点 if(last == node) { memset(tlist, 0, sizeof(TCircleList)); } return node; } CircleListNode* CircleList_Get(CircleList *list, int pos) { TCircleList *tlist; CircleListNode *current, *last = NULL, *node; int i; if(NULL == list || pos < 0) { printf("CircleList_Get err (NULL == list || pos < 0)\n"); return NULL; } tlist = (TCircleList *)list; if(pos >= tlist->length) { printf("CircleList_Get err (pos >= tlist->length)\n"); return NULL; } current = &tlist->header; for(i = 0; i<pos; i++) current = current->next; node = current->next; return node; } CircleListNode* CircleList_DeleteNode(CircleList *list, CircleListNode *node) { TCircleList *tlist; int i; CircleListNode *current, *ret = NULL; if(NULL == list || NULL == node) { printf("CircleList_DeleteNode err (NULL == list || NULL == node)\n"); return NULL; } tlist = (TCircleList *)list; current = &tlist->header; for(i = 0; i < tlist->length; i++) { if(current->next == node) { ret = current->next; break; } current = current->next; } if(ret != NULL) CircleList_Delete(list, i); return ret; } CircleListNode* CircleList_Reset(CircleList *list) { TCircleList *tlist; CircleListNode *ret = NULL; if(NULL == list) { printf("CircleList_Reset err (NULL == list)\n"); return NULL; } tlist = (TCircleList *)list; tlist->slider = tlist->header.next; return tlist->slider; } CircleListNode* CircleList_Current(CircleList *list) { TCircleList *tlist; CircleListNode *ret = NULL; if(NULL == list) { printf("CircleList_Current err (NULL == list)\n"); return NULL; } tlist = (TCircleList *)list; return tlist->slider; } CircleListNode* CircleList_Next(CircleList *list) { TCircleList *tlist; CircleListNode *ret = NULL; if(NULL == list) { printf("CircleList_Next err (NULL == list)\n"); return NULL; } tlist = (TCircleList *)list; ret = tlist->slider; if(tlist->slider != NULL) tlist->slider = tlist->slider->next; return ret; }
测试代码:
#include <stdlib.h> #include <string.h> #include <stdio.h> #include "CircleList.h" typedef struct _Teacher { CircleListNode node; int age; char name[64]; }Teacher; typedef struct _Teacher2 { CircleListNode node; int age; char name[64]; }Teacher2; typedef struct _Teacher3 { CircleListNode node; int age; char name[64]; int age3; }Teacher3; //一般功能测试 void main12() { int ret = 0, i = 0; CircleList* list = NULL; Teacher t1, t2, t3, t4,t5; t1.age = 31; t2.age = 32; t3.age = 33; t4.age = 34; t5.age = 35; list = CircleList_Create(); if (list == NULL) { printf("func CircleList_Create(10) ret :%d \n", ret); return ; } ret = CircleList_Insert(list, (CircleListNode*) &t1, 0); //头插法 ret = CircleList_Insert(list, (CircleListNode*) &t2, 0); //头插法 ret = CircleList_Insert(list, (CircleListNode*) &t3, 0); //头插法 ret = CircleList_Insert(list, (CircleListNode*) &t4, 0); //头插法 ret = CircleList_Insert(list, (CircleListNode*) &t5, 0); //头插法 //遍历 for (i=0; i<CircleList_Length(list); i++) { Teacher* tmp = (Teacher *) CircleList_Get(list, i); if (tmp == NULL) { return ; } printf("tmp->age:%d ", tmp->age); } //删除链表中的节点 while( CircleList_Length(list) > 0 ) { CircleList_Delete(list, 0); } system("pause"); return ; } struct Value { CircleListNode header; int v; }; //循环链表解决约瑟夫问题 void main() { int i = 0; CircleList* list = CircleList_Create(); struct Value v1, v2, v3, v4, v5, v6, v7, 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, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v6, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v7, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v8, CircleList_Length(list)); for(i=0; i<CircleList_Length(list); i++) { //获取游标所指元素,然后游标下移 struct Value* pv = (struct Value*)CircleList_Next(list); printf("%d\n", pv->v); } printf("\n"); //重置游标 CircleList_Reset(list); while( CircleList_Length(list) > 0 ) { struct Value* pv = NULL; for(i=1; i<3; i++) { CircleList_Next(list); } pv = (struct Value*)CircleList_Current(list); printf("%d\n", pv->v); CircleList_DeleteNode(list, (CircleListNode*)pv); } CircleList_Destory(list); system("pause"); return ; }
总结:
循环链表比一般链表增加了循环的能力,但是还是没有解决链表逆向遍历耗时的缺点,
所以循环链表的实用性并没有质的提升,但是对于接下来搞懂循环双向链表至关重要。