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

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

1) 普通插入元素(和单链表是一样的)

2) 尾插法(和单链表是一样的,单链表的写法支持尾插法;

因:辅助指针向后跳length次,指向最后面那个元素)

CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list));

CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list));

1) 头插法(要进行头插法,需要求出尾结点,和单链表不一样的地方,保证是循环链表)

第一次插入元素时,让游标指向0号结点

CircleList_Insert(list, (CircleListNode*)&v1, 0);

CircleList_Insert(list, (CircleListNode*)&v1, 0);

4)第一次插入元素

循环链表插入综合场景分析图

循环链表删除结点分析

1、 删除普通结点

2、 删除头结点(删除0号位置处元素),需要求出尾结点

优点:功能强了。

循环链表只是在单链表的基础上做了一个加强

循环链表可以完全取代单链表的使用

循环链表的Next和Current操作可以高效的遍历链表中的所有元素

#ifndef _CIRCLELIST_H_
#define _CIRCLELIST_H_
/*
typedef struct _tag_CircleListNode CircleListNode;
struct _tag_CircleListNode
{
CircleListNode* next;
};
*/
typedef void T; typedef struct _tag_CircleListNode
{
struct _tag_CircleListNode * next;
}CircleListNode; T* CircleList_Create(); void List_Destroy(T* list); void CircleList_Clear(T* list); int CircleList_Length(T* list); int CircleList_Insert(T* list, CircleListNode* node, int pos); CircleListNode* CircleList_Get(T* list, int pos); CircleListNode* CircleList_Delete(T* list, int pos); //add //根据结点的值 进行数据的删除
CircleListNode* CircleList_DeleteNode(T* list, CircleListNode* node); CircleListNode* CircleList_Reset(T* list); CircleListNode* CircleList_Current(T* list); //游标指向2号位置
//把2号位置返回出来,同时让游标下移到3号位置
CircleListNode* CircleList_Next(T* list); #endif
#include <stdio.h>
#include <malloc.h>
#include "CircleList.h" typedef struct _tag_CircleList//循环链表结构体(头结点,游标,长度)
{
CircleListNode header;//头结点
CircleListNode* slider;//游标
int length;
} TCircleList; T* CircleList_Create() // O(1)初始化链表结构体
{
TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));
if (ret == NULL)
{
return NULL;
} ret->length = ;
ret->header.next = NULL;
ret->slider = NULL;
return ret;
} void CircleList_Destroy(T* list) // O(1)
{
if (list == NULL)
{
return ;
}
free(list);
} void CircleList_Clear(T* list) // O(1)
{
TCircleList* sList = (TCircleList*)list;
if (sList == NULL)
{
return ;
}
sList->length = ;
sList->header.next = NULL;
sList->slider = NULL;
} int CircleList_Length(T* list) // O(1)
{
TCircleList* sList = (TCircleList*)list;
int ret = -;
if (list == NULL)
{
return ret;
}
ret = sList->length;
return ret;
} int CircleList_Insert(T* list, CircleListNode* node, int pos) // O(n)
{
int ret = , i=;
TCircleList* sList = (TCircleList*)list; if (list == NULL || node== NULL || pos<)
{
return -;
} CircleListNode* current = (CircleListNode*)sList;//头结点 for(i=; (i<pos) && (current->next != NULL); i++)
{
current = current->next;
} //current->next 0号节点的地址
node->next = current->next; //
current->next = node; //2 //若第一次插入节点
if( sList->length == )//这里游标一直指向第0号位置
{
sList->slider = node;
} sList->length++; //若头插法 current仍然指向头部
//(原因是:跳0步,没有跳走)
if( current == (CircleListNode*)sList )
{
//获取最后一个元素
CircleListNode* last = CircleList_Get(sList, sList->length - );
last->next = current->next; //
} return ret;
} CircleListNode* CircleList_Get(T* list, int pos) // O(n)
{
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL;
int i = ; if (list==NULL || pos<)
{
return NULL;
}
//if( (sList != NULL) && (pos >= 0) && (sList->length > 0) )
{
CircleListNode* current = (CircleListNode*)sList; for(i=; i<pos; i++)
{
current = current->next;
} ret = current->next;
} return ret;
} CircleListNode* CircleList_Delete(T* list, int pos) // O(n)
{
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL;
int i = ; if( (sList != NULL) && (pos >= ) && (sList->length > ) )
{
CircleListNode* current = (CircleListNode*)sList;
CircleListNode* last = NULL; for(i=; i<pos; i++)
{
current = current->next;
} //若删除第一个元素(头结点)
if( current == (CircleListNode*)sList )
{
last = (CircleListNode*)CircleList_Get(sList, sList->length - );
} //求要删除的元素
ret = current->next;
current->next = ret->next; sList->length--; //判断链表是否为空
if( last != NULL )
{
sList->header.next = ret->next;
last->next = ret->next;
} //若删除的元素为游标所指的元素
if( sList->slider == ret )
{
sList->slider = ret->next;
} //若删除元素后,链表长度为0
if( sList->length == )
{
sList->header.next = NULL;
sList->slider = NULL;
}
} return ret;
} CircleListNode* CircleList_DeleteNode(T* list, CircleListNode* node) // O(n)
{
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL;
int i = ; if( sList != NULL )
{
CircleListNode* current = (CircleListNode*)sList; //查找node在循环链表中的位置i
for(i=; i<sList->length; i++)
{
if( current->next == node )
{
ret = current->next;
break;
} current = current->next;
} //如果ret找到,根据i去删除
if( ret != NULL )
{
CircleList_Delete(sList, i); //根据结点的值 求出结点的位置 ,根据位置删除元素
}
} return ret;
} CircleListNode* CircleList_Reset(T* list) // O(1)
{
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL; if( sList != NULL )
{
sList->slider = sList->header.next;
ret = sList->slider;
} return ret;
} CircleListNode* CircleList_Current(T* list) // O(1)
{
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL; if( sList != NULL )
{
ret = sList->slider;
} return ret;
} //把当前位置返回,并且游标下移
//把当前游标所指的位置的元素返回出去
//游标下移
CircleListNode* CircleList_Next(T* 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;
}
#include <stdio.h>
#include <stdlib.h>
#include "CircleList.h" struct Value
{
CircleListNode circlenode;
int v;
}; int main11()
{
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; int i = ; v1.v = ;
v2.v = ;
v3.v = ;
v4.v = ;
v5.v = ;
v6.v = ;
v7.v = ;
v8.v = ; CircleList_Insert(list, (CircleListNode*)&v1, );
CircleList_Insert(list, (CircleListNode*)&v2, );
CircleList_Insert(list, (CircleListNode*)&v3, );
CircleList_Insert(list, (CircleListNode*)&v4, ); for(i=; i<*CircleList_Length(list); i++) //怎么样证明是循环链表
{
struct Value* pv = (struct Value*)CircleList_Get(list, i); printf("%d\n", pv->v);
} while( CircleList_Length(list) > )
{
CircleList_Delete(list, );
} printf("\n"); CircleList_Destroy(list); system("pause"); return ;
}
#include <stdio.h>
#include <stdlib.h>
#include "CircleList.h" struct Value
{
CircleListNode header;
int v;
}; void main()
{
int i = ;
CircleList* list = CircleList_Create(); struct Value v1, v2, v3, v4, v5, v6, v7, v8; v1.v = ; v2.v = ; v3.v = ; v4.v = ;
v5.v = ; v6.v = ; v7.v = ; v8.v = ; 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=; i<CircleList_Length(list); i++)
{
//获取游标所指元素,然后游标下移
struct Value* pv = (struct Value*)CircleList_Next(list);
printf("%d ", pv->v);
} printf("\n"); //重置游标
CircleList_Reset(list); while( CircleList_Length(list) > )
{
struct Value* pv = NULL;
for(i=; i<; i++)
{
CircleList_Next(list);
}
pv = (struct Value*)CircleList_Current(list);
printf("%d ", pv->v);
CircleList_DeleteNode(list, (CircleListNode*)pv); //根据结点的值,进行结点元素的删除
} CircleList_Destroy(list); system("pause");
return ;
}

C 循环链表的更多相关文章

  1. java程序设计之循环链表

    照例来说点废话,愿自己生一颗温柔细腻的心,这样女朋友也许一个眼神,一个微笑,我就知道如何做,可惜内心与外表一样粗糙,这一生有幸认识她,愿天下有情人终成眷属. 循环链表,顾名思义循环就好了,所以建一个线 ...

  2. 单链表、循环链表的JS实现

    数据结构系列前言: 数据结构作为程序员的基本知识,需要我们每个人牢牢掌握.近期我也展开了对数据结构的二次学习,来弥补当年挖的坑......   当时上课的时候也就是跟着听课,没有亲自实现任何一种数据结 ...

  3. 双向链表、双向循环链表的JS实现

    关于链表简介.单链表.单向循环链表.JS中的使用以及扩充方法:  单链表.循环链表的JS实现 关于四种链表的完整封装: https://github.com/zhuwq585/Data-Structu ...

  4. JAVA 链表操作:循环链表

    主要分析示例: 一.循环链表简述 二.单链表循环链表 三.双链表循环链表 一.循环链表简述 循环链表即链表形成了一个循环的结构,尾节点不再指向NULL,而是指向头节点HEAD,此时判定链表的结束是尾节 ...

  5. Have Fun with Numbers及循环链表(约瑟夫问题)

    1. 循环链表(约瑟夫问题) https://github.com/BodhiXing/Data_Structure 2. Have Fun with Numbers https://pta.pate ...

  6. javascript中使用循环链表实现约瑟夫环问题

    1.问题 传说在公元1 世纪的犹太战争中,犹太历史学家弗拉维奥·约瑟夫斯和他的40 个同胞被罗马士兵包围.犹太士兵决定宁可自杀也不做俘虏,于是商量出了一个自杀方案.他们围成一个圈,从一个人开始,数到第 ...

  7. Linux内核循环链表经典分析和移植

    为什么说这个链表做的经典呢,哥哥我从Linux内核里边儿扣出来的,要么怎么说内核不是一般人能写的,这代码太TM优美了! 这里有一篇参考文章:http://isis.poly.edu/kulesh/st ...

  8. C语言通用双向循环链表操作函数集

    说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低.     可基于该函数集方便地构造栈或队列集.     本函数集暂未考虑并发保护. 一  ...

  9. 双向循环链表的Java版本实现

    1.单项循环列表 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环.和单链表相比,循环单链表的长处是从链尾到链 ...

  10. C++ 模板双向不循环链表!!

    CTDChain<T,sort,equal,pointer> * nodeTemp = NULL; -------------------------------------------- ...

随机推荐

  1. 2009国家集训队小Z的袜子

    莫队算法? 感觉没什么优越性啊?难道就是因为在排序的时候cmp函数的不同?这样做为什么减少时限啊? 我带着疑惑敲了代码,却一直有bug…… 代码: type node=record l,r,id,x, ...

  2. spring-webmvc 4.3.4 与 freemarker、easyui 整合

    一.所需lib包 二.web.xml配置 <?xml version="1.0" encoding="UTF-8"?> <web-app xm ...

  3. 15个极好的Linux find命令示例(二)

    前阵子,我们审查了15件实事 find命令的例子(第一部分).查找命令可以做很多比只是在寻找基于名称的文件 (第2部分)在这篇文章中,让我们来讨论15高级find命令的例子, 包括-根据它访问,修改或 ...

  4. JQuery focus()

    跳转到登陆页面时可以使用focus方法 <input name="login_account"id="login_account"class=" ...

  5. 使用SVN小结

    自从加入团队后,开始使用SVN,以下是个人对SVN的一些认识和小结. 一.SVN是什么? SVN是版本管理工具,譬如团队进行项目开发,项目代码都储存在服务器上,成员可用SVN在本地获得并更新代码. 二 ...

  6. [转载]DIV CSS设计时IE6、IE7、FF 与兼容性有关的特性

    在网站设计的时候,应该注意css样式兼容不同浏览器问题,特别是对完全使用DIV CSS设计的网,就应该更注意IE6 IE7 FF对CSS样式的兼容,不然,你的网乱可能出去不想出现的效果! 所有浏览器 ...

  7. NGINX(七)分段下载

    前言 nginx分段下载通过ngx_http_range_filter_module模块进行处理,关于HTTP分段下载过程,可以参考HTTP分段下载一文,主要分为一次请求一段和一次请求多段 涉及数据结 ...

  8. 如何学习ios开发

    著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Franz Fang链接:http://www.zhihu.com/question/20264108/answer/3026 ...

  9. iOS程序性能优化

    iOS程序性能优化 一.初级 使用ARC进行内存管理 在iOS5发布的ARC,它解决了最常见的内存泄露问题.但是值得注意的是,ARC并不能避免所有的内存泄露.使用ARC之后,工程中可能还会有内存泄露, ...

  10. 网页加载速度优化2--先加载css,然后再加载js文件。

    网页加载时,是按从上到下,从左到右的顺序加载的.所以一定要先加载css文件(不要让用户看到一个杂乱无章的页面),最后再加载js文件,js一般都是处理功能的,所以不需要提前加载.先给用户观感,再给用户上 ...