循环链表的实现
说明
实现
- circular_list.h
#ifndef _CIRCULAR_LIST_H_ #define _CIRCULAR_LIST_H_ #ifdef __cplusplus extern "C"{ #endif typedef void CIRCULAR_LIST; // 循环链表类型 typedef struct CIRCULAR_LIST_NODE // 循环链表节点类型 { struct CIRCULAR_LIST_NODE* next; }CIRCULAR_LIST_NODE; /* 创建循环链表,返回循环链表的地址 */ CIRCULAR_LIST* CircularList_Create(); /* 销毁循环链表的空间 */ void CircularList_Destroy(CIRCULAR_LIST* list); /* 清空循环链表的元素 */ void CircularList_Clear(CIRCULAR_LIST* list); /* 获取循环链表中元素的个数 */ int CircularList_Length(CIRCULAR_LIST* list); /* 获取循环链表中下标为pos的元素的地址 */ CIRCULAR_LIST_NODE* CircularList_Get(CIRCULAR_LIST* list, int pos); /* 在下标为pos的位置插入元素node,返回实际插入的位置 */ int CircularList_Insert(CIRCULAR_LIST* list, CIRCULAR_LIST_NODE* node, int pos); /* 删除循环链表中下标为pos的节点 */ CIRCULAR_LIST_NODE* CircularList_Delete(CIRCULAR_LIST* list, int pos); /* 删除循环链表中的节点node */ CIRCULAR_LIST_NODE* CircularList_DeleteNode(CIRCULAR_LIST* list, CIRCULAR_LIST_NODE* node); /* 重置游标 */ CIRCULAR_LIST_NODE* CircularList_ResetSlider(CIRCULAR_LIST* list); /* 获取当前游标指向的节点 */ CIRCULAR_LIST_NODE* CircularList_Current(CIRCULAR_LIST* list); /* 返回当前游标指向的节点,并且游标向前移动一步 */ CIRCULAR_LIST_NODE* CircularList_SliderNext(CIRCULAR_LIST* list); #ifdef __cplusplus } #endif #endif
- circular_list.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "circular_list.h" typedef struct TAG_CIRCULAR_LIST { CIRCULAR_LIST_NODE header; CIRCULAR_LIST_NODE* slider; int length; }TAG_CIRCULAR_LIST; /* 创建循环链表,返回循环链表的地址 */ CIRCULAR_LIST* CircularList_Create() { TAG_CIRCULAR_LIST* circular_list = NULL; // 申请头节点 circular_list = (TAG_CIRCULAR_LIST*)malloc(sizeof(TAG_CIRCULAR_LIST)); if(circular_list == NULL) { printf("func CircularList_Create() err: circular_list == NULL\n"); return NULL; } // 给申请的空间赋一个初值 memset(circular_list, 0, sizeof(TAG_CIRCULAR_LIST)); return circular_list; } /* 销毁循环链表的空间 */ void CircularList_Destroy(CIRCULAR_LIST* list) { TAG_CIRCULAR_LIST* circular_list = NULL; // 检查输入 if (list == NULL) { printf("func CircularList_Destroy() err: list == NULL\n"); return ; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 避免野指针 if (circular_list != NULL) { free(circular_list); circular_list = NULL; } return; } /* 清空循环链表的元素 */ void CircularList_Clear(CIRCULAR_LIST* list) { TAG_CIRCULAR_LIST* circular_list = NULL; // 检查输入 if (list == NULL) { printf("func CircularList_Clear() err: list == NULL\n"); return; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 清空链表 memset(circular_list, 0, sizeof(TAG_CIRCULAR_LIST)); return; } /* 获取循环链表中元素的个数 */ int CircularList_Length(CIRCULAR_LIST* list) { TAG_CIRCULAR_LIST* circular_list = NULL; // 检查输入 if (list == NULL) { printf("func CircularList_Length() err: list == NULL\n"); return -1; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; return circular_list->length; } /* 获取循环链表中下标为pos的元素的地址 */ CIRCULAR_LIST_NODE* CircularList_Get(CIRCULAR_LIST* list, int pos) { TAG_CIRCULAR_LIST* circular_list = NULL; CIRCULAR_LIST_NODE* current_ptr = NULL; int i = 0; // 检查输入 if (list == NULL || pos < 0) { printf("func CircularList_Get() err: list == NULL || pos < 0\n"); return NULL; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 检查位置合法性 if (pos >= circular_list->length) { printf("func CircularList_Get() err: pos >= circular_list->length\n"); return NULL; } // 将辅助指针移动到pos位置前一个位置 current_ptr = (CIRCULAR_LIST_NODE*)circular_list; for (i = 0; i < pos; ++i) { current_ptr = current_ptr->next; } // 返回pos位置的地址 return current_ptr->next; } /* 在下标为pos的位置插入元素node,返回实际插入的位置 */ int CircularList_Insert(CIRCULAR_LIST* list, CIRCULAR_LIST_NODE* node, int pos) { TAG_CIRCULAR_LIST* circular_list = NULL; CIRCULAR_LIST_NODE* current_ptr = NULL; CIRCULAR_LIST_NODE* last_ptr = NULL; int i = 0; // 检查输入 if (list == NULL || node == NULL || pos < 0) { printf("func CircularList_Insert() err: list == NULL || node == NULL || pos < 0\n"); return -1; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 容错检查:当pos >= circular_list->length时,采用尾插法 if (pos >= circular_list->length) { pos = circular_list->length; } // 将辅助指针变量跳转到pos-1位置 current_ptr = (CIRCULAR_LIST_NODE*)circular_list; for (i = 0; i < pos; ++i) { current_ptr = current_ptr->next; } // 按照单向链表方式直接插入节点 node->next = current_ptr->next; current_ptr->next = node; circular_list->length++; // 处理特殊情况 // 如果此次插入之前循环链表没有节点,需要将链表最后一个节点指向第一个节点 if (circular_list->length == 1) { node->next = node; } // 如果此次插入之前已经有了节点,并且在0号位置插入,正常插入之后最后一个节点指向的节点变成第2个节点,需要修正 if (circular_list->length != 1 && current_ptr == (CIRCULAR_LIST_NODE*)circular_list) { // 获取最后一个节点 last_ptr = (CIRCULAR_LIST_NODE*)circular_list; for(i = 0; i < circular_list->length; ++i) { last_ptr = last_ptr->next; } // 将最后一个节点指向第一个节点 last_ptr->next = current_ptr->next; } return pos; } /* 删除循环链表中下标为pos的节点 */ CIRCULAR_LIST_NODE* CircularList_Delete(CIRCULAR_LIST* list, int pos) { TAG_CIRCULAR_LIST* circular_list = NULL; CIRCULAR_LIST_NODE* deleted_node = NULL; CIRCULAR_LIST_NODE* current_ptr = NULL; CIRCULAR_LIST_NODE* last_ptr = NULL; int i = 0; // 检查输入 if (list == NULL || pos < 0) { printf("func CircularList_Delete() err: list == NULL || pos < 0\n"); return NULL; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 检查pos的合法性 if (pos >= circular_list->length) { printf("func CircularList_Delete() err: pos >= circular_list->length\n"); return NULL; } // 将current_ptr移动到pos-1的位置 current_ptr = (CIRCULAR_LIST_NODE*)circular_list; for (i = 0; i < pos; ++i) { current_ptr = current_ptr->next; } // 按照单向链表的方式删除节点 deleted_node = current_ptr->next; current_ptr->next = deleted_node->next; circular_list->length--; // 处理特殊情况 // 如果此次删除之后循环链表中将没有节点,那么此次删除之后circular_list->header->next将指向被删除的元素,需要将其置零 if (circular_list->length == 0) { current_ptr->next = NULL; } // 如果此次删除之后循环链表中还有节点,并且这次删除的是第一个节点,那么删除之后,最后一个节点指向的是一个已经删除的节点,需要修正 if (circular_list->length > 0 && current_ptr == (CIRCULAR_LIST_NODE*)circular_list) { // 获取最后一个节点 last_ptr = (CIRCULAR_LIST_NODE*)circular_list; for (i = 0; i < circular_list->length; ++i) { last_ptr = last_ptr->next; } // 将最后一个节点指向第一个节点 last_ptr->next = current_ptr->next; } return deleted_node; } /* 删除循环链表中的节点node */ CIRCULAR_LIST_NODE* CircularList_DeleteNode(CIRCULAR_LIST* list, CIRCULAR_LIST_NODE* node) { TAG_CIRCULAR_LIST* circular_list = NULL; int i = 0; CIRCULAR_LIST_NODE* current_ptr = NULL; CIRCULAR_LIST_NODE* deleted_node = NULL; // 参数检查 if (list == NULL || node == NULL) { printf("func CircularList_DeleteNode() err: list == NULL || node == NULL\n"); return NULL; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 遍历循环链表,找到和node相同的节点就退出循环 current_ptr = (CIRCULAR_LIST_NODE*)circular_list; for(i = 0; i < circular_list->length; ++i) { current_ptr = current_ptr->next; if (current_ptr == node) { deleted_node = current_ptr; break; } } // 如果查找不到node,报错;找到node之后删除 if (i >= circular_list->length) { printf("func CircularList_DeleteNode() err: node is not in circular list\n"); return NULL; } else if(i < circular_list->length) { CircularList_Delete(circular_list, i); } return deleted_node; } /* 重置游标,返回重置之后游标指向的节点 */ CIRCULAR_LIST_NODE* CircularList_ResetSlider(CIRCULAR_LIST* list) { TAG_CIRCULAR_LIST* circular_list = NULL; // 参数检查 if (list == NULL) { printf("func CircularList_ResetSlider() err: list == NULL\n"); return NULL; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 重置slider circular_list->slider = circular_list->header.next; return circular_list->slider; } /* 获取当前游标指向的节点 */ CIRCULAR_LIST_NODE* CircularList_Current(CIRCULAR_LIST* list) { TAG_CIRCULAR_LIST* circular_list = NULL; // 参数检查 if (list == NULL) { printf("func CircularList_Current() err: list == NULL\n"); return NULL; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 返回节点,使用者自己保证游标指向的正确性 return circular_list->slider; } /* 返回当前游标指向的节点,并且游标向前移动一步 */ CIRCULAR_LIST_NODE* CircularList_SliderNext(CIRCULAR_LIST* list) { TAG_CIRCULAR_LIST* circular_list = NULL; CIRCULAR_LIST_NODE* current_ptr = NULL; // 参数检查 if (list == NULL) { printf("func CircularList_SliderNext() err: list == NULL\n"); return NULL; } // 将CIRCULAR_LIST_NODE类型的地址转换为TAG_CIRCULAR_LIST类型的地址 circular_list = (TAG_CIRCULAR_LIST*)list; // 记录当前游标位置 current_ptr = circular_list->slider; // 如果循环列表没有节点,报错 if (circular_list->length == 0) { printf("func CircularList_SliderNext() err: circular_list->length == 0\n"); return NULL; } else { circular_list->slider = circular_list->slider->next; } return current_ptr; }
- test.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "circular_list.h" /* 约瑟夫问题:N个人围成一圈,由第一个人从1开始报数,报M的人会被淘汰,然后从后一个人重新开始报数,重复以上过程,求出淘汰的人的顺序 */ /* 业务结构,包含一个节点域和一个整形域 */ typedef struct VALUE { CIRCULAR_LIST_NODE* circular_node; int value; }VALUE; int main(void) { int i = 0; int number_of_people = 16; // 16个人围成一圈 int death_number = 3; // 报数为3的人死亡 VALUE* v = NULL; CIRCULAR_LIST* circular_list = NULL; // 创建循环链表 circular_list = CircularList_Create(); if (circular_list == NULL) { printf("func main(): circular_list == NULL\n"); return -1; } // 设置随机数种子 srand((unsigned int)time(NULL)); // 随机生成16个人的value for (i = 0; i < number_of_people; ++i) { v = (VALUE*)malloc(sizeof(VALUE)); v->circular_node = NULL; v->value = rand()%100; // 随机生成[0,100)的value值 // 使用头插法插入循环链表 CircularList_Insert(circular_list, (CIRCULAR_LIST_NODE*)v, 0); } // 打印循环链表(人围成的圈的顺序) for (i = 0; i < CircularList_Length(circular_list); ++i) { v = (VALUE*)CircularList_Get(circular_list, i); printf("%d ",v->value); } printf("\n"); // 重置游标,使其指向第一个节点 CircularList_ResetSlider(circular_list); // 报数,并开始淘汰 while (CircularList_Length(circular_list) > 0) { // 报数,开始之后第1个人和第death_number个人中间隔着(death_number - 1)跳 for (i = 0; i < (death_number - 1); ++i) { CircularList_SliderNext(circular_list); } // 此时游标刚好指向淘汰的人,通过游标得到这个人的信息,并将这个人踢出游戏 v = (VALUE*)CircularList_Current(circular_list); CircularList_SliderNext(circular_list); // 删除之前先将游标移动到下一个开始的位置 CircularList_DeleteNode(circular_list, (CIRCULAR_LIST_NODE*)v); // 处理淘汰的节点:1. 输出; 2. 销毁空间(循环链表的库不负责销毁) printf("%d\n",v->value); if(v != NULL) { free(v); v = NULL; } } // 销毁循环链表 CircularList_Destroy(circular_list); printf("Hello world!\n"); return 0; }