关于单向循环链表的创建、插入、删除、遍历

关于单向循环链表的创建、插入、删除、遍历、

单向循环链表的公式

image

单向循环链表的代码

#include <stdio.h>       // 标准输入输出头文件
#include <string.h>      // 字符串处理头文件        memset/清空
#include <stdlib.h>      // 标准库头文件            malloc/申请堆空间
#include <unistd.h>      // sleep延时//宏定义数据
#define DATA_LEN 20
#define SEARCH_MODE_PRESENT 1 //找当前
#define SEARCH_MODE_BEFOR   2 //上一个//定义结构体类型
typedef struct loop_link_node
{//数据域char data[DATA_LEN];//指针域struct loop_link_node * next;
}LOOP_LINK_NODE,*P_LINK;/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 函数声明文件 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */P_LINK Create_New_Node();                                       // 声明一个创建新节点的函数
P_LINK Retrieve_Add_Node(P_LINK head_node,int search_mode);     // 声明一个目标检索函数
int Mode_Selection(P_LINK head_node);                           // 声明一个功能选择函数,检测链表各种模式
int Head_Add_Node(P_LINK head_node);                            // 声明一个头插函数
int Ergodic_List_Node(P_LINK head_node);                        // 声明一个遍历函数
int Tail_Add_Node(P_LINK head_node);                            // 声明一个尾插函数
int Appoint_Add_Node(P_LINK head_node);                         // 声明一个指定位置插入函数
int Del_Add_Node(P_LINK head_node);                             // 声明一个指定位置删除函数/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 函数声明文件 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */// 定义一个函数,来创建一个新节点
P_LINK Create_New_Node()
{//申请新节点的内存空间P_LINK new_node = (P_LINK)malloc(sizeof(LOOP_LINK_NODE));if(new_node == (P_LINK)NULL)//检查内存是否申请成功{perror("malloc ...");return (P_LINK)-1;}//清空memset(new_node,0,sizeof(LOOP_LINK_NODE));//新节点的指针指向自己,体现循环new_node->next = new_node;return new_node; //返回申请的新节点
}// 创建一个功能函数用来进行检测操作链表的插入、删除、遍历、检索
int Mode_Selection(P_LINK head_node)
{// 如果头节点为空,输出提示信息并返回错误码if (head_node == (P_LINK)NULL){printf("头节点为空!\n");return -1;}int select_num; // 用于存放用户输入的选择编号while (1)       // 无限循环,直到用户选择退出{system("clear"); // 清屏// 显示菜单项printf("<<<< 1 头插添加数据节点 >>>>\n");printf("<<<< 2 尾插添加数据节点 >>>>\n");printf("<<<< 3 指定检索数据节点 >>>>\n");printf("<<<< 4 指定添加数据节点 >>>>\n");printf("<<<< 5 指定删除数据节点 >>>>\n");printf("<<<< 6 遍历链表数据节点 >>>>\n");printf("<<<< 7 退出单向循环链表 >>>>\n");// 获取用户的指令输入scanf("%d", &select_num);// 根据用户选择进行相应的操作switch (select_num){case 1:Head_Add_Node(head_node);break;                          // 头插法添加数据节点case 2:Tail_Add_Node(head_node);break;                          // 尾插法添加数据节点case 3:Retrieve_Add_Node(head_node,SEARCH_MODE_PRESENT);break;  // 检索目标数据节点并返回case 4:Appoint_Add_Node(head_node);break;                       // 目标位置添加数据节点case 5:Del_Add_Node(head_node);break;                           // 指定位置删除节点 case 6:Ergodic_List_Node(head_node);break;                      // 遍历整个链表并输出显示case 7:return 0;                                                // 退出单向循环链表default:printf("没有此项指令,请重新输入!\n");break;              // 输入无效,提示重新输入}sleep(1); // 延时1秒,使用户能看到执行结果}return 0;
}//头插法,插入链表
int Head_Add_Node(P_LINK head_node)
{//判断头节点是否异常if(head_node == (P_LINK)NULL){printf("head node abnormal");return -1;}//创建新节点P_LINK new_node = Create_New_Node();if(new_node == (P_LINK)NULL){printf("Create new node faile");return -1;}printf("输入待插入的数据:");scanf("%s",new_node->data);while(getchar() !='\n');   // 清空输入缓冲区new_node->next = head_node->next; //新节点的下一个指针指向头节点的下一个的指针head_node->next = new_node;       //新节点的下一个指向新节点printf("头插成功!数据:%s----地址:%p\n",new_node->data,new_node);return 0;
}// 定义函数 Tail_Add_Node,用于在单向循环链表中尾部位置删除节点
int Tail_Add_Node(P_LINK head_node)
{//判断头节点是否异常if(head_node == (P_LINK)NULL){printf("head node abnormal\n");return -1;}//创建新节点P_LINK new_node = Create_New_Node();if(new_node == (P_LINK)NULL){printf("Create new node faile");return -1;}//输入尾插数据printf("输入尾插数据:");scanf("%s",new_node->data);while(getchar() != '\n'); //清空输入缓冲区//声明尾节点变量P_LINK end_node;//遍历找到尾节点for(end_node = head_node; end_node->next != head_node; end_node = end_node->next);new_node->next = end_node->next; //新节点的下一个指针指向尾节点的下一个end_node->next = new_node;       //尾节点的下一个指针指向新节点printf("尾插成功!数据:%s----地址:%p\n",new_node->data,new_node);return 0;
}//检索整个链表
P_LINK Retrieve_Add_Node(P_LINK head_node,int search_mode)
{//判断头节点是否异常if(head_node == (P_LINK)NULL){printf("head node abnormal\n");return (P_LINK)-1;}//判断是否是空链表if(head_node->next == head_node){printf("空链表,无需检索!\n");return (P_LINK)0;}//定义目标数据节点char obj_data[DATA_LEN]="\0";printf("输入目标数据:");scanf("%s",obj_data);//循环遍历找目标节点for(P_LINK tmp_node = head_node; tmp_node->next != head_node; tmp_node = tmp_node->next){//如果成立,则tmp_node就是上一个结点if(strcmp(tmp_node->next->data,obj_data) == 0){printf("找到该节点:数据:%s---地址:%p\n",tmp_node->next->data,tmp_node->next);if(search_mode == SEARCH_MODE_PRESENT)  // 判断是否临时节点的下一个节点{return tmp_node->next;              // 返回临时节点的下一个节点}if(search_mode == SEARCH_MODE_BEFOR)    // 判断是否临时节点{return tmp_node;                    // 返回临时节点}}}return (P_LINK)0;
}// 定义函数 Appoint_Add_Node,用于在单向循环链表中指定位置插入新节点
int Appoint_Add_Node(P_LINK head_node)
{//判断头节点异常if(head_node == NULL){printf("头节点异常!\n");return -1;}//判断链表是否为空else if(head_node->next == head_node){printf("空链表默认尾插!\n");if(Tail_Add_Node(head_node) == -1){printf("默认头插失败!\n");return -1;}}else{//创建目标节点P_LINK obj_node = Retrieve_Add_Node(head_node,SEARCH_MODE_PRESENT);if(obj_node == (P_LINK)-1){printf("链表异常!目标节点创建失败!\n");return -1;}//判断是否有目标节点else if(obj_node == (P_LINK)0){printf("没有找到目标节点!\n");return 0;}//找到目标节点进行插入else{//创建新节点P_LINK new_node = Create_New_Node();if(new_node == (P_LINK)NULL){printf("创建新节点失败!\n");return -1;}printf("输入插入的数据:");// 从标准输入读取新节点数据scanf("%s",new_node->data);while(getchar() !='\n');// 清空输入缓冲区//调整指针指向,完成插入new_node->next = obj_node->next;  //新节点的下一个指针指向目标节点的下一个obj_node->next = new_node;        //目标节点的下一个指向新节点printf("指定插入完成!\n");}}return 0;
}// 定义函数 Del_Add_Node,用于删除单向循环链表中的指定节点
int Del_Add_Node(P_LINK head_node)
{//判断头节点是否异常if(head_node == NULL){printf("链表异常!\n");return -1;}//判断是否是空链表else if(head_node->next == head_node){printf("空链表无需删除!\n");return -1;}else{//检索被删除的上一个节点P_LINK before_del_node = Retrieve_Add_Node(head_node,SEARCH_MODE_BEFOR);if(before_del_node == (P_LINK)-1){printf("链表异常,无法删除!\n");return -1;}//判断是否有要删除的节点数据else if(before_del_node == (P_LINK)0){printf("未找到要删除的目标节点!\n");return 0;}else{//找到删除节点,进行删除操作printf("数据的删除:");//创建被删除的节点P_LINK del_node       = before_del_node->next; //被删除节点的上一个指向的创建的被删除的节点before_del_node->next = del_node->next;        //被删除节点的上一个指向被删除节点的下一个指针del_node->next        = NULL;                  //被删除的节点指针指向空printf("删除节点成功!\n");//释放删除节点空间free(del_node);return 0;}}
}// 定义函数 Ergodic_List_Node,用于遍历单向循环链表并在用户终端显示
int Ergodic_List_Node(P_LINK head_node)
{//判断头节点是否异常if(head_node == (P_LINK)NULL){printf("head node abnormal");return -1;}//判断是不是空链表else if(head_node->next == head_node){printf("空链表,无需遍历!\n");return 0;}else{//循环遍历输出显示地址与插入的数据for(P_LINK tmp_node = head_node->next; tmp_node->next != head_node->next; tmp_node = tmp_node->next){printf("数据:%s----地址:%p\n",tmp_node->data,tmp_node);}}return 0;
}int main()
{//创建一个头节点P_LINK head_node = Create_New_Node();if(head_node == (P_LINK)NULL)//判断单向循环链表是否创建成功{printf("创建单向循环链表失败!\n");return -1;}else{printf("创建单向循环链表成功!\n");}//调用功能函数Mode_Selection(head_node);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/708026.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AnimationCurve关键帧数值修改小工具

效果图 用途:界面动效已经由动效人员A做完(假设k了100帧),然后UI同事又把一些节点的位置做了10px的调整 此时一帧一帧去手动改,费事费力还可能出错。 这个工具的用途就是:对相关节点的所有关键帧批量做偏移。public class AnimClipEditWnd : EditorWindow {[MenuItem(&quo…

elastic使用postman操作

1、账号认证 2、elastic索引put请求,创建索引 get请求,查询所有索引get请求,查询索引 delete请求,删除索引 put请求,增加文档数据 get请求,查询文档数据简单查询,按id简单查询,查询固定index索引下的所有数据 修改数据整条修改局部修改

Python没有服务器如何部署运行Shiny应用程序

原文链接:https://tecdat.cn/?p=36205 原文出处:拓端数据部落公众号 随着Web技术的快速发展,越来越多的数据科学家和开发人员倾向于使用Web应用程序进行数据分析和可视化。Shiny for Python作为一种流行的Web应用程序框架,为Python开发人员提供了便捷的数据展示和交互工具…

R语言CART决策树、随机森林、chaid树预测母婴电商平台用户寿命、流失可视化

全文链接:http://tecdat.cn/?p=31644 原文出处:拓端数据部落公众号 借着二胎政策的开放与家庭消费升级的东风,母婴市场迎来了生机盎然的春天,尤其是母婴电商行业,近年来发展迅猛。用户获取和流失是一对相对概念,就好比一个水池,有进口,也有出口。我们不能只关心进口的…

Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用|附代码数据

原文链接:http://tecdat.cn/?p=24407 最近我们被客户要求撰写关于金融时间序列模型的研究报告,包括一些图形和统计输出。 这篇文章讨论了自回归综合移动平均模型 (ARIMA) 和自回归条件异方差模型 (GARCH) 及其在股票市场预测中的应用 ( 点击文末“阅读原文”获取完整代码数…

R语言中绘图设置不输出绘图内容

001、正常绘图plot(1:10, cex = 2, pch = 19) 002、不输出绘图内容plot(1:10, cex = 2, pch = 19, type = "n") 。

AnimationClip获取关键帧信息

1,关键帧数据都保存在AnimationCurve上,所以首先要获取到这个public static AnimationCurve GetAnimCurve(AnimationClip clip, string path, string propName) {EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);foreach (var b in bindings){if (…

Dism壳 (做系统的启动盘 多系统版本install.wim合成 界面化)

做系统优盘的时候不断的dism来dism去有些烦了 做了个小工具可以代替bat了... 没做异常处理 开始预览镜像把素材拖进去开始制作流程点击空动作后会出现创建的动作类型 其中合成就是把多个系统搓在一起用的 上面的索引代表的正是双击看到的那些信息的索引 输入对应索引然后空格分…

项目管理之八大绩效域------笔记(三)

18.3 开发方法和生命周期绩效域跟开发方法,项目交付节奏和生命周期相关的活动和职能.一、预期目标:①开发方法与项目可交付物相符合;②将项目交付与干系人价值紧密关联;③项目生命周期由促进交付节奏的项目阶段和产生项目交付物所需的开发方法组成。(项目周期的设计符合项目的…

CSAPP第二章

gcc指定不同的C语言版本 注意寻址和字节顺序讲的, 对象的地址都是从小地址开始算起, 而所谓大端法就是高位字节在前; 小端法则是低位字节在前 注意: 等号上的小圆点的组合表示"被定义为"的意思 反码有+0和-0, -0就是全为1的位模式, 负数的反码就是对应正数所有位取反…

R语言中判断数值是否带有小数点

001、不为整数> a <- 5.324 > floor(a) == a ## 截断后不相等, 说明带有小数点部分,即不为整数 [1] FALSE 002、是整数> b <- 324 > floor(b) == b ## 截断小数点后仍然相等,说明是整数 [1] TRUE 。

poj 3061 Subsequence

题目链接: 来自罗勇军《算法竞赛》书中的习题。 题意:给长度为 \(N\) 的数组和一个整数 \(S\),求总和不小于 \(S\) 的连续子序列的最小长度。 方法一:尺取法 主要思想为:当 \(a_1, a_2 , a_3\) 满足和 \(\geqslant S\),得到一个区间长度 \(3\), 那么去掉开头 \(a_1\),剩…