单循环链表(基于c语言)
#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语言)的更多相关文章
- 基于链表的C语言堆内存检测
说明 本文基于链表实现C语言堆内存的检测机制,可检测内存泄露.越界和重复释放等操作问题. 本文仅提供即视代码层面的检测机制,不考虑编译链接级的注入或钩子.此外,该机制暂未考虑并发保护. 相关性文章参见 ...
- (续)顺序表之单循环链表(C语言实现)
单循环链表和单链表的唯一区别在于单循环链表的最后一个节点的指针域指向第一个节点, 使得整个链表形成一个环. C实现代码如下: #include<stdio.h> typedef struc ...
- 数据结构篇(2) ts实现单循环链表
JS的class可以通过extends关键字实现类似其他语言的继承效果,比起使用一个extends关键字,在es5中实现继承要复杂一些,可以通过修改原型链的方法实现继承,让一个原型对象等于另一个类型的 ...
- 关于《selenium2自动测试实战--基于Python语言》
关于本书的类型: 首先在我看来技术书分为两类,一类是“思想”,一类是“操作手册”. 对于思想类的书,一般作者有很多年经验积累,这类书需要细读与品位.高手读了会深有体会,豁然开朗.新手读了不止所云,甚至 ...
- 《Selenium2自动化测试实战--基于Python语言》 --即将面市
发展历程: <selenium_webdriver(python)第一版> 将本博客中的这个系列整理为pdf文档,免费. <selenium_webdriver(python)第 ...
- Gogs - 基于 Go 语言的自助 Git 服务
Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务.Gogs 的目标是打造一个最简单.最快速和最轻松的方式搭建自助 Git 服务.使用 Go 语言开发使得 Gogs ...
- Ggoogle Protocol Buffer的使用 (基于C++语言)
首先说明的是Protocol Buffle是灵活高效的.它的一个很好的优点(很重要的,我认为)就是后向兼容性--当我们扩展了了.proto文件后,我们照样可以用它来读取之前生成的文件. 之前已经写了关 ...
- 基于C# 语言的两个html解析器
基于C# 语言的两个html解析器 1)Html Agility Pack http://nsoup.codeplex.com/ 代码段示例: HtmlDocument doc = new HtmlD ...
- springmvc国际化 基于浏览器语言的国际化配置
当前标签: springmvc springmvc国际化 基于浏览器语言的国际化配置 苏若年 2013-10-09 13:03 阅读:305 评论:0 SpringMVC中应用Ajax异步通讯 ...
- 基于JAVA语言的多线程技术
1.简介 多线程技术属于操作系统范围内的知识: 进程与线程 可以这么理解,一个应用程序就是一个进程,在一个进程中包含至少一个线程:进程就是线程的容器,真正工作.处理任务的是线程. 进程是操作系统分配资 ...
随机推荐
- VUE3 之 动态组件 - 这个系列的教程通俗易懂,适合新手
1. 概述 暗示效应告诉我们: 巧妙的暗示会在不知不觉中剥夺我们的判断力,对我们的思维形成一定的影响,造成我们行为的些许改变或者偏差. 例如你的朋友说你脸色不太好,是不是病了,此时,你可能就会感觉浑身 ...
- Solution -「多校联训」排水系统
\(\mathcal{Description}\) Link. 在 NOIP 2020 A 的基础上,每条边赋权值 \(a_i\),随机恰好一条边断掉,第 \(i\) 条段的概率正比于 \(a ...
- Solution -「NOI.AC 省选膜你赛」寄蒜几盒
题目 题意简述 给定一个含有 \(n\) 个顶点的凸多边形( \(n\) 是偶数),对于每一对相对的边(即中间有 \(\frac{n}2-1\) 条其它边),延长它们以将平面分割为多块,并把包含原 ...
- 猜猜我在哪里-linux查找命令
文章目录 find findfs locate slocate which whereis pwd pwdx find: # 这是一个很强大的查找命令 findfs: # 依据卷标(LABEL)和UU ...
- CSS代码示例-背景属性(background)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [LeetCode]1389. 按既定顺序创建目标数组
给你两个整数数组 nums 和 index.你需要按照以下规则创建目标数组: 目标数组 target 最初为空. 按从左到右的顺序依次读取 nums[i] 和 index[i],在 target 数组 ...
- 每日一题:codeforces题解
题目 B. Peculiar Movie Preferences time limit per test 2 seconds memory limit per test 512 megabytes i ...
- [转自Matrix67] 趣题:顶点数为多少的图有可能和自己互补
若干个顶点以及某些顶点和顶点之间的连线,就构成了一个"图".如果对某个图进行变换,使得原来任意两个有连线的顶点之间都不再有连线,原来任意两个没有连线的顶点之间现在都有连线了,那么所 ...
- ansible复习笔记_playbook-从零到无
--创建时间:2021年3月9日 --修改时间:2021年3月9日 --作者:飞翔的小胖猪 yaml语法格式 每单一文件第一行,使用 "---"开始.在结尾的时候使用三个点&quo ...
- idea教程--如何使用码云管理代码
1.安装Gitee插件 由于我已经安装过了,请参加白色背景的图 2.idea配置git 3.配置码云账号 4.配置ssh秘钥(注意:如果之前安装git已经配置过了可以跳过此步) (1) 生成SSH秘钥 ...