您的位置:首页 > 其它

循环链表设计与API实现

2015-07-12 16:42 381 查看
基本概念

循环链表的定义:将单链表中最后一个数据元素的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位置插入结点node
int 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位置插入结点node
int 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;
}

// 若删除元素后链表长度为0
if (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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: