循环链表设计与API实现

来源:互联网 发布:安卓动态桌面软件 编辑:程序博客网 时间:2024/05/22 05:01

基本概念
循环链表的定义:将单链表中最后一个数据元素的next指针指向第一个元素

循环链表拥有单链表的所有操作

创建链表
销毁链表
获取链表长度
清空链表
获取第pos个元素操作
插入元素到位置pos
删除位置pos处的元素

新增功能:游标的定义

在循环链表中可以定义一个“当前”指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。

循环链表新操作

将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list);

获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list);

将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list);

直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);
// 根据元素的值 删除 元素 pk根据元素的位置 删除 元素

最后加了一个循环链表的应用:求解约瑟夫问题

约瑟夫问题-循环链表典型应用
n 个人围成一个圆圈,首先第 1 个人从 1 开始一个人一个人顺时针报数,报到第 m 个人,令其出列。然后再从下一 个人开始从 1 顺时针报数,报到第 m 个人,再令其出列,…,如此下去,求出列顺序。

代码:

// circlelist.h// 循环链表API声明#ifndef _CIRCLELIST_H_#define _CIRCLELIST_H_typedef void CircleList;typedef struct _tag_CircleListNode{struct _tag_CircleListNode *next;}CircleListNode;// 创建链表CircleList* CircleList_Create();// 销毁链表void CircleList_Destroy(CircleList* list);// 清空链表void CircleList_Clear(CircleList* list);// 获取链表的长度int CircleList_Length(CircleList* list);// 在pos位置插入结点nodeint CircleList_Insert(CircleList* list,CircleListNode* node, int pos);// 获取pos位置的结点CircleListNode* CircleList_Get(CircleList* list, int pos);// 删除pos位置的结点CircleListNode* CircleList_Delete(CircleList* list, int pos);// 根据结点的值进行数据删除CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);// 重置游标CircleListNode* CircleList_Reset(CircleList* list);// 获取当前游标所指结点CircleListNode* CircleList_Current(CircleList* list);// 将原始游标所指结点返回给上层,然后让游标移到下一个结点CircleListNode* CircleList_Next(CircleList* list);#endif

// circlelist.cpp// 循环链表API实现#include <iostream>#include <cstdio>#include "circlelist.h"typedef struct _tag_CircleList{CircleListNode header;CircleListNode *silder;int length;}TCircleList;// 创建链表CircleList* CircleList_Create(){TCircleList *ret = (TCircleList *)malloc(sizeof(TCircleList));if (ret == NULL) {return NULL;}// 初始化ret->header.next = NULL;ret->silder = NULL;ret->length = 0;return ret;}// 销毁链表void CircleList_Destroy(CircleList* list){if (list == NULL) {return;}free(list);return;}// 清空链表void CircleList_Clear(CircleList* list){if (list == NULL) {return;}TCircleList *tList = (TCircleList *)list;tList->header.next = NULL;tList->silder = NULL;tList->length = 0;return;}// 获取链表的长度int CircleList_Length(CircleList* list){if (list == NULL) {return -1;}TCircleList *tList = (TCircleList *)list;return tList->length;}// 在pos位置插入结点nodeint CircleList_Insert(CircleList* list, CircleListNode* node, int pos){if (list == NULL || node == NULL || pos < 0) {return -1;}TCircleList *tList = (TCircleList *)list;CircleListNode *cur = (CircleListNode *)tList;for (int i = 0; i < pos; ++i) {cur = cur->next;}node->next = cur->next;cur->next = node;// 如果是第一次插入if (tList->length == 0) {tList->silder = node;}++tList->length; // 记得长度加1// 如果是头插法if (cur == (CircleListNode *)tList) {// 获取最后一个元素CircleListNode *last = CircleList_Get(tList, tList->length - 1);last->next = cur->next;}return 0;}// 获取pos位置的结点CircleListNode* CircleList_Get(CircleList* list, int pos){// 因为是循环链表,所以这里不需要排除pos>length的情况if (list == NULL || pos < 0) {return NULL;}TCircleList *tList = (TCircleList *)list;CircleListNode *cur = (CircleListNode *)tList;for (int i = 0; i < pos; ++i) {cur = cur->next;}return cur->next;}// 删除pos位置的结点CircleListNode* CircleList_Delete(CircleList* list, int pos){TCircleList *tList = (TCircleList *)list;CircleListNode *ret = NULL;if (tList != NULL && pos >= 0 && tList->length > 0) {CircleListNode *cur = (CircleListNode *)tList;for (int i = 0; i < pos; ++i) {cur = cur->next;}// 若删除头结点,需要求出尾结点CircleListNode *last = NULL;if (cur == (CircleListNode *)tList)  {last = CircleList_Get(tList, tList->length - 1);}ret = cur->next;cur->next = ret->next;--tList->length;// 若删除头结点if (last != NULL) {tList->header.next = ret->next;last->next = ret->next;}// 若删除的元素为游标所指的元素if (tList->silder == ret) {tList->silder = ret->next;}// 若删除元素后链表长度为0if (tList->length == 0) {tList->header.next = NULL;tList->silder = NULL;}}return ret;}// 根据结点的值进行数据删除CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node){TCircleList *tList = (TCircleList *)list;CircleListNode *ret = NULL;if (list != NULL && node != NULL) {CircleListNode *cur = (CircleListNode *)tList;int i = 0;for (i = 0; i < tList->length; ++i) {if (cur->next == node) {ret = cur->next;break;}cur = cur->next;}// 如果找到if (ret != NULL) {CircleList_Delete(tList, i);}}return ret;}// 重置游标CircleListNode* CircleList_Reset(CircleList* list){TCircleList *tList = (TCircleList *)list;CircleListNode* ret = NULL;if (list != NULL) {tList->silder = tList->header.next;ret = tList->silder;}return NULL;}// 获取当前游标所指结点CircleListNode* CircleList_Current(CircleList* list){TCircleList *tList = (TCircleList *)list;CircleListNode* ret = NULL;if (list != NULL) {ret = tList->silder;}return ret;}// 将原始游标所指结点返回给上层,然后让游标移到下一个结点CircleListNode* CircleList_Next(CircleList* list){TCircleList *tList = (TCircleList *)list;CircleListNode* ret = NULL;if (list != NULL && tList->silder != NULL) {ret = tList->silder;tList->silder = ret->next;}return ret;}

// joseph.h// 用循环链表API求解约瑟夫问题#include <cstdio>#include "circlelist.h"const int maxp = 8;struct Person{CircleListNode circlenode;int id;};void joseph(){Person s[maxp];for (int i = 0; i < maxp; ++i) {s[i].id = i + 1;}CircleList *list = NULL;list = CircleList_Create();// 插入元素for (int i = 0; i < maxp; ++i) {// 尾插法int ret = CircleList_Insert(list, (CircleListNode *)&s[i], CircleList_Length(list));if (ret < 0) {printf("function CircleList_Insert err: %d\n", ret);}}// 遍历链表for (int i = 0; i < CircleList_Length(list); ++i) {Person *tmp = (Person *)CircleList_Get(list, i);if (tmp == NULL) {printf("function CircleList_Get err.\n");}printf("age: %d\n", tmp->id);}// 求解约瑟夫问题while (CircleList_Length(list) > 0){Person* pv = NULL;for (int i = 1; i < 3; i++){CircleList_Next(list);}pv = (Person*)CircleList_Current(list);printf("%d ", pv->id);CircleList_DeleteNode(list, (CircleListNode *)pv); //根据结点的值,进行结点元素的删除}printf("\n");CircleList_Destroy(list);}

// main.cpp// 循环链表测试程序#include <iostream>#include <cstdio>#include "circlelist.h"#include "joseph.h"const int maxn = 5;struct Student{CircleListNode circlenode;char name[32];int age;};void play01(){Student s[maxn];for (int i = 0; i < maxn; ++i) {s[i].age = i + 1;}CircleList *list = NULL;list = CircleList_Create(); // 创建链表// 插入元素for (int i = 0; i < maxn; ++i) {// 尾插法int ret = CircleList_Insert(list, (CircleListNode *)&s[i], CircleList_Length(list));if (ret < 0) {printf("function CircleList_Insert err: %d\n", ret);}}// 遍历链表// 这里遍历打印两边,可以证明这是一个循环链表for (int i = 0; i < 2 * CircleList_Length(list); ++i) {Student *tmp = (Student *)CircleList_Get(list, i);if (tmp == NULL) {printf("function CircleList_Get err.\n");}printf("age: %d\n", tmp->age);}// 删除结点,通过结点位置while (CircleList_Length(list)) {Student *tmp = (Student *)CircleList_Delete(list, CircleList_Length(list) - 1);if (tmp == NULL) {printf("function CircleList_Delete err.\n");}printf("age: %d\n", tmp->age);}// 销毁链表CircleList_Destroy(list);}int main(){play01(); // 为了测试数据的生命周期,所以另写一个函数调用运行joseph();return 0;}

0 0