#include <stdio.h>
#include <stdlib.h>
#include <assert.h> typedef int LDataType;
typedef struct Linklist{
LDataType data;
struct Linklist *next;
}Linklist,*pLinklist; pLinklist BuyNewNode(LDataType data); //动态生成新结点
void InitLinklist(pLinklist *pL); //初始化单链表
void PushBackLinklist(pLinklist *pL,LDataType data); //尾插
void PushFrontLinklist(pLinklist *pL,LDataType data); //头插
void PopBackLinklist(pLinklist* pL); //尾删
void PopFrontLinklist(pLinklist *pL); //头删
void PrintLinklist(Linklist *pL); //打印单链表
pLinklist FindLinklist(pLinklist *pL,LDataType data); //查找指定元素,返回元素位置
//void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data); //指定位置插入
void RemoveLinklist(pLinklist* pL,LDataType data); //删除第一个指定元素
void RemoveAllLinklist(pLinklist *pL,LDataType data); //删除所有指定元素
int IsEmptyLinklist(pLinklist pL); //判断链表是否为空
void DestoryLinklist(pLinklist *pL); //销毁单链表 int main(void){
Linklist *first = NULL;
InitLinklist(&first);
int people_num = 10;
int each = 3;
int return_num = 0;
for (int i=0;i<10;i++){
PushBackLinklist(&first,i+1);
}
int i = 1;
Linklist *another = first;
Linklist *pre;
PrintLinklist(first);
puts(" ");
while(1){
if(another->next == first && first->next == another && first == another){
PrintLinklist(first);
break;
}
if(i%3 == 0){
pre = another->next;
RemoveLinklist(&first,another->data);
i++;
another = pre;
PrintLinklist(first);
puts(" ");
}else{
another = another->next;
i++;
} } // Linklist *first = NULL;
// InitLinklist(&first);
// for (int i=0;i<10;i++){
// PushBackLinklist(&first,i+1);
// }
// PrintLinklist(first);
// puts(" ");
// RemoveLinklist(&first,7);
// PrintLinklist(first);
} //循环链表与开辟内存区域无关
pLinklist BuyNewNode(LDataType data){
pLinklist NewNode = (pLinklist)malloc(sizeof(Linklist));
if (NewNode == NULL){
printf("动态开辟内存空间失败\n");
return NULL;
}
NewNode->data = data;
NewNode->next = NULL;
return NewNode;
}
void InitLinklist(pLinklist *pL){
assert(pL != NULL); //初始化操作
(*pL) = NULL;
}
void PushBackLinklist(pLinklist *pL,LDataType data){
//主要就是从尾部插入的元素应该要指向头指针
assert(pL != NULL); //尾插一个数据域为data的结点
pLinklist NewNode = BuyNewNode(data);
if(*pL == NULL){
*pL = NewNode;
NewNode->next = *pL;
return ;
}
pLinklist cur = *pL;
while(cur->next != *pL){
cur = cur->next;
}
NewNode->next = cur->next;
cur->next = NewNode;
}
void PushFrontLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL); //头插一个数据域为data的结点
pLinklist NewNode = BuyNewNode(data);
if(*pL == NULL){
*pL = NewNode;
NewNode->next = *pL;
return ;
}
NewNode->next = *pL;
*pL = NewNode;
pLinklist pre = NewNode->next;
while(pre->next != NewNode->next){
pre = pre->next;
}
pre->next = *pL;
}
int IsEmptyLinklist(pLinklist pL){
return (pL == NULL); //判断无头单链表是否为空
}
void PopBackLinklist(pLinklist *pL){
assert(pL != NULL); //尾删
if(IsEmptyLinklist(*pL)){
puts("链表为空,删除失败");
return ;
}
pLinklist cur = *pL;
pLinklist pre;
if(cur->next == *pL){
//只有一个结点
*pL = NULL;
free(cur);
cur = NULL;
return ;
}
while(cur->next != *pL){
pre = cur;
cur = cur->next;
}
pre->next = *pL;
free(cur);
cur = NULL;
}
void PopFrontLinklist(pLinklist *pL){
assert(pL != NULL); //头删,既是删除第一个结点
if(*pL == NULL){
printf(" 链表为空,删除失败");
return ;
}
pLinklist cur = *pL;
if(cur->next == *pL){
*pL = NULL;
free(cur);
cur = NULL;
return ;
}
*pL = cur->next;
free(cur);
cur = NULL;
}
pLinklist FindLinklist(pLinklist *pL,LDataType data){
assert( pL != NULL); //找到第一个数据为data的结点
pLinklist cur = *pL; while(cur->next != *pL){
if (cur->data == data){
return cur;
}
cur = cur->next;
}
if(cur->data == data){
return cur;
} return NULL;
}
//void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data){
// assert(pL != NULL); //xiangp结点之前插入一个数据为data的元素
// pLinklist NewNode = BuyNewNode(data);
// pLinklist cur = *pL;
// while(cur->next != p){
// cur = cur->next;
// }
// NewNode->next = p;
// cur->next = NewNode;
//}
void RemoveLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL); //删除第一个数据域为data的结点
pLinklist cur = NULL;
pLinklist p = *pL;
pLinklist pre = NULL;
cur = FindLinklist(pL,data);
if (cur == NULL){
printf("未找到要删除的元素");
return ;
}
if (*pL == cur){
//位于第一个结点
// *pL = cur->next;
// free(cur);
// cur = NULL;
// return ;
pLinklist each_node = *pL;
while(each_node->next != *pL){
each_node = each_node->next;
}
each_node->next = (*pL)->next;
*pL = (*pL)->next;
free(cur);
cur = NULL;
return ;
}
while(p != cur){
pre = p;
p = p->next;
}
pre->next = cur->next;
free(cur);
cur = NULL;
}
void RemoveAllLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL); //删除每一个数据域都是data的结点
pLinklist cur = NULL;
pLinklist p = *pL;
pLinklist pre = *pL;
while(p->next != *pL){
if (p->data == data && (*pL) == p){
//第一个结点是
pLinklist each_node = *pL;
while(each_node->next != *pL){
each_node = each_node->next;
}
each_node->next = (*pL)->next;
pre = p;
p = p->next;
*pL = p;
free(pre);
pre = NULL; }
else if(p->data == data){
//后续结点是
cur = p;
p = p->next;
pre->next = p;
free(cur);
cur = NULL;
}
else{
//此结点不是
pre = p;
p = p->next;
}
}
}
void PrintLinklist(Linklist *pL){
pLinklist cur = pL; //打印链表
if(cur->next == pL){
printf("%d--->",cur->data);
}else{
while(cur->next != pL){
printf("%d--->",cur->data);
cur = cur->next;
}
printf("%d--->",cur->data);
}
printf("头"); }
void DestoryLinklist(pLinklist *pL){
assert(pL != NULL); //摧毁链表
pLinklist cur = *pL;
pLinklist pre = NULL;
if (*pL == NULL){
printf("链表为空");
return ;
}
if (cur->next = *pL){
*pL = NULL;
free(cur);
cur = NULL;
return ;
}
while(cur->next != *pL){
pre = cur;
cur = cur->next;
free(pre);
pre = NULL;
}
}

这个代码是我在单链表的基础上改的,顺便实现了一下一个Josephus算法。其他的值是可以输入的。

在写这个代码的时候唯一难一点的就是头插,头删这两个操作。

头插:首先要判断是否为空,如果为空的话直接插入,然后再指向自己或者指向*pL就行了;但是如果有元素的话,头插就不是那么简单了,我们可以看一下下面的图,很明显,我们需要将新的结点的link域指向*pL,然后将*pL指向新的结点,这还没有完!!
然后现在的链表并不是我们想要的一个循环链表,所以我们要找到最后一个结点再让他指向新的结点。

头删:我感觉这个和上面头删是一样的,上面的只要掌握了,自然也就会头部删除了。先判断是否为空……

单循环链表(基于c语言)的更多相关文章

  1. 基于链表的C语言堆内存检测

    说明 本文基于链表实现C语言堆内存的检测机制,可检测内存泄露.越界和重复释放等操作问题. 本文仅提供即视代码层面的检测机制,不考虑编译链接级的注入或钩子.此外,该机制暂未考虑并发保护. 相关性文章参见 ...

  2. (续)顺序表之单循环链表(C语言实现)

    单循环链表和单链表的唯一区别在于单循环链表的最后一个节点的指针域指向第一个节点, 使得整个链表形成一个环. C实现代码如下: #include<stdio.h> typedef struc ...

  3. 数据结构篇(2) ts实现单循环链表

    JS的class可以通过extends关键字实现类似其他语言的继承效果,比起使用一个extends关键字,在es5中实现继承要复杂一些,可以通过修改原型链的方法实现继承,让一个原型对象等于另一个类型的 ...

  4. 关于《selenium2自动测试实战--基于Python语言》

    关于本书的类型: 首先在我看来技术书分为两类,一类是“思想”,一类是“操作手册”. 对于思想类的书,一般作者有很多年经验积累,这类书需要细读与品位.高手读了会深有体会,豁然开朗.新手读了不止所云,甚至 ...

  5. 《Selenium2自动化测试实战--基于Python语言》 --即将面市

    发展历程: <selenium_webdriver(python)第一版>   将本博客中的这个系列整理为pdf文档,免费. <selenium_webdriver(python)第 ...

  6. Gogs - 基于 Go 语言的自助 Git 服务

    Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务.Gogs 的目标是打造一个最简单.最快速和最轻松的方式搭建自助 Git 服务.使用 Go 语言开发使得 Gogs ...

  7. Ggoogle Protocol Buffer的使用 (基于C++语言)

    首先说明的是Protocol Buffle是灵活高效的.它的一个很好的优点(很重要的,我认为)就是后向兼容性--当我们扩展了了.proto文件后,我们照样可以用它来读取之前生成的文件. 之前已经写了关 ...

  8. 基于C# 语言的两个html解析器

    基于C# 语言的两个html解析器 1)Html Agility Pack http://nsoup.codeplex.com/ 代码段示例: HtmlDocument doc = new HtmlD ...

  9. springmvc国际化 基于浏览器语言的国际化配置

    当前标签: springmvc   springmvc国际化 基于浏览器语言的国际化配置 苏若年 2013-10-09 13:03 阅读:305 评论:0   SpringMVC中应用Ajax异步通讯 ...

  10. 基于JAVA语言的多线程技术

    1.简介 多线程技术属于操作系统范围内的知识: 进程与线程 可以这么理解,一个应用程序就是一个进程,在一个进程中包含至少一个线程:进程就是线程的容器,真正工作.处理任务的是线程. 进程是操作系统分配资 ...

随机推荐

  1. WebGPU 中消失的 FBO 和 RBO

    目录 1 WebGL 中的 FBO 与 RBO 1.1 帧缓冲对象(FramebufferObject) 1.2 颜色附件与深度模板附件的真正载体 1.3 FBO/RBO/WebGLTexture 相 ...

  2. 帆软报表(finereport) 组合地图 保持系列名和值居中

    自定义JavaScript代码,使用HTML解析 function(){ var name = this.name; var total = '<div style="width:10 ...

  3. HTML笔记整理--下节

    欢迎来到HTML基础笔记下节部分! 内联样式 当特殊的样式需要应用到个别元素时,就可以使用内联样式. 使用内联样式的方法是在相关的标签中使用样式属性.样式属性可以包含任何 CSS 属性.以下实例显示出 ...

  4. CSRF跨站请求伪造漏洞分析

    CSRF 现在的网站都有利用CSRF令牌来防止CSRF,就是在请求包的字段加一个csrf的值,防止csrf,要想利用该漏洞,要和xss组合起来,利用xss获得该csrf值,在构造的请求中将csrf值加 ...

  5. Linux性能优化实战(二)

    一.CPU使用率过高 1,CPU使用率 a>节拍率 为了维护CPU时间,Linux通过事先定义的节拍率(内核中表示为HZ),触发时间中断,并使用全局变量Jiffies记录开机以来的节拍数.每发生 ...

  6. LRU缓存及实现

    一.淘汰策略 缓存:缓存作为一种平衡高速设备与低速设备读写速度之间差异而引入的中间层,利用的是局部性原理.比如一条数据在刚被访问过只有就很可能再次被访问到,因此将其暂存到内存中的缓存中,下次访问不用读 ...

  7. VUE3 之 动画与过渡的实现 - 这个系列的教程通俗易懂,适合新手

    1. 概述 光环效应告诉我们: 当一个人在某一方面取得了巨大的成功,人们就会给他贴上正面的标签,这个人从此就被"优秀"的光环所笼罩,他做的一切,人们都认为是正确的. 例如:越是名气 ...

  8. 手撸一个springsecurity,了解一下security原理

    手撸一个springsecurity,了解一下security原理 转载自:www.javaman.cn 手撸一个springsecurity,了解一下security原理 今天手撸一个简易版本的sp ...

  9. CobaltStrike逆向学习系列(14):CS功能分析-DotNet

    这是[信安成长计划]的第 14 篇文章 0x00 目录 0x01 DotNet功能分析 0x02 DotNet功能执行 0x03 写在最后 在上两篇文章中,讲述了 CS 中的一种功能执行方式 RDI, ...

  10. 3款大数据bi工具,让企业数据分析更简单

    ​企业数据可视化的髙速发展趋势让互联网时代的数据分析及可视化拥有全新的面貌.企业针对信息内容的数据分析及可视化,的要求在日益严格,那么有哪些在企业数据分析方面做得好的大数据bi工具呢? 一.大数据bi ...