C语言 实现链表的各种功能

C语言实现链表的各种功能

链表的定义

链表是一种数据结构,它是由一系列节点组成的线性结构。每个节点包含两个部分:数据和指针。数据部分存储着实际的数据,指针部分指向下一个节点。

链表的特点是:

  • 每个节点都可以自由地插入或删除。
  • 链表的第一个节点称为头节点,最后一个节点称为尾节点。
  • 链表中节点的数量可以动态变化。

链表的实现

链表的实现可以分为两步:

  1. 定义链表节点的结构。
  2. 实现链表的操作函数。

定义链表节点的结构

文件名:link_list.h#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>typedef int ElemType;typedef struct linkList{ElemType data;struct linkList* next;
}LNode;//初始化链表
bool initList(LNode** head);//链表是否为空
bool isEmpty(LNode* head);//链表长度
int length(LNode* head);//链表头部插入元素
bool insert(LNode* head, ElemType data);//链表尾部插入元素
bool append(LNode* head, ElemType data);//插入链表指定位置
bool insertAt(LNode* head, ElemType data, int pos);//链表删除元素头删
bool delete(LNode* head);//链表删除指定位置元素
bool deleteAt(LNode* head, int pos);//删除链表元素尾删
bool deleteTail(LNode* head);//链表中查找指定位置元素
LNode* searchAt(LNode* head, int pos);//修改链表指定位置元素
bool modify(LNode* head, ElemType data, int pos);//清空链表
bool clearList(LNode* head);//销毁链表
bool destroyList(LNode** head);//打印链表
bool printList(LNode* head);

实现链表的操作函数

文件名:link_list.c#include "link_list.h"#define DEBUG_PRINT 1//初始化链表
bool initList(LNode** head){if(NULL==head){
#if DEBUG_PRINTprintf("初始化链表的入参为空\n");
#endifreturn false;}//初始化  calloc()申请的空间自动初始化为0(*head)=(LNode*)calloc(1, sizeof(LNode));(*head)->next=NULL;(*head)->data=0;//头节点中数据用来保存链表中的元素个数return true;
}
//链表是否为空
bool isEmpty(LNode* head){if(NULL==head){
#if DEBUG_PRINTprintf("isEmpty()的入参为空\n");
#endifreturn false;}if(head->next==NULL){return true;}return false;
}
//链表长度
int length(LNode* head){if(NULL==head){
#if DEBUG_PRINTprintf("length()的入参为空\n");
#endifreturn false;}return head->data;
}
//链表头部插入元素
bool insert(LNode* head, ElemType data){//入参判断if(NULL==head){
#if DEBUG_PRINTprintf("insert()的入参为空\n");
#endifreturn false;}//为新节点申请空间LNode * newNode=(LNode*)calloc(1, sizeof(LNode));newNode->data=data;newNode->next=head->next;head->next=newNode;head->data++;
}
//链表尾部插入元素
bool append(LNode* head, ElemType data){//入参判断if(NULL==head){
#if DEBUG_PRINTprintf("insert()的入参为空\n");
#endifreturn false;}//为新节点申请空间LNode * newNode=(LNode*)calloc(1, sizeof(LNode));newNode->data=data;// LNode *temp=head->next;//head->next可能为NULL,下方对temp->next=(NULL->next),会报错LNode *temp=head;while (temp->next!=NULL){temp=temp->next;}newNode->next=temp->next;temp->next=newNode;head->data++;return true;
}
//插入链表指定位置
bool insertAt(LNode* head, ElemType data, int pos){//入参判断if(NULL==head){
#if DEBUG_PRINTprintf("insertAt()的入参为空\n");
#endifreturn false;}if(pos<0|| pos>head->data ){
#if DEBUG_PRINTprintf("insertAt()的插入位置不合理\n");
#endifreturn false;}LNode *temp=head;int  flg=0;//标记循环的次数是否到了插入位置 ,没到说明插入位置不合理for (int i = 0; i < pos; ++i) {flg++;if(temp->next!=NULL){temp=temp->next;} else{break;}}if(flg==pos){//为新节点申请空间LNode * newNode=(LNode*)calloc(1, sizeof(LNode));newNode->data=data;newNode->next= temp->next;temp->next=newNode;head->data++;return true;} else{return false;}
}
//链表删除元素头删
bool delete(LNode* head){//入参判断if(NULL==head){
#if DEBUG_PRINTprintf("delete()的入参为空\n");
#endifreturn false;}if(isEmpty(head)){printf("链表已空\n");return true;}LNode *temp=head->next;head->next=head->next->next;free(temp);head->data--;return true;}
//链表删除指定位置元素
bool deleteAt(LNode* head, int pos){//入参判断if(NULL==head ){
#if DEBUG_PRINTprintf("deleteAt()的入参为空\n");
#endifreturn false;}if(NULL==head->next){ //要判断NULL==head->next 下面temp=head->nextprintf("空表不能删除\n");return false;}if(pos<0|| pos >= head->data ){
#if DEBUG_PRINTprintf("deleteAt()的删除位置不合理\n");
#endifreturn false;}LNode *temp=head->next; //temp=head->next保证删除0位置也正常返回LNode *P=head;int flg=0;for (int i = 0; i < pos; ++i) {flg++;if(temp->next!=NULL){ //保证temp->next不能指空P=temp;temp=temp->next;} else{break;}}if(flg==pos){//查0位置不走循环,返回了temp=head->nextP->next=temp->next;free(temp);head->data--;return true;} else{return false;}}
//删除链表元素尾删
bool deleteTail(LNode* head){//入参判断if(NULL==head ){
#if DEBUG_PRINTprintf("delete()的入参为空\n");
#endifreturn false;}//只有头节点无需删除if(NULL==head->next){printf("表只有头节点\n");return true;}//找到尾节点的前一个节点LNode *temp=head;LNode * P=NULL;while (temp->next!=NULL){P=temp;temp=temp->next;}if(P){//循环退出时P指向尾节点的前一个节点,temp就是尾节点P->next=NULL;free(temp);head->data--;}return true;
}
//链表中查找指定位置元素
LNode* searchAt(LNode* head, int pos){//入参判断if(NULL==head ){
#if DEBUG_PRINTprintf("insertAt()的入参为空\n");
#endifreturn false;}if(NULL==head->next){ //要判断NULL==head->next 下面temp=head->nextprintf("空表不能查询\n");return false;}if(pos<0|| pos >= head->data ){
#if DEBUG_PRINTprintf("searchAt()的查找位置不合理\n");
#endifreturn false;}LNode *temp=head->next; //temp=head->next保证查0位置也正常返回int flg=0;for (int i = 0; i < pos; ++i) {flg++;if(temp!=NULL){temp=temp->next;} else{break;}}if(flg==pos){//查0位置不走循环,返回了temp=head->nextreturn temp;} else{return false;}}
//修改链表指定位置元素
bool modify(LNode* head, ElemType data, int pos){//入参判断if(NULL==head ){
#if DEBUG_PRINTprintf("modify()的入参为空\n");
#endifreturn false;}if(NULL==head->next){ //要判断NULL==head->next 下面temp=head->nextprintf("空表不能查询\n");return false;}if(pos<0|| pos >= head->data ){
#if DEBUG_PRINTprintf("modify()的修改位置不合理\n");
#endifreturn false;}LNode *temp=head->next; //temp=head->next保证修改0位置也正常返回int flg=0;for (int i = 0; i < pos; ++i) {flg++;if(temp!=NULL){temp=temp->next;} else{break;}}if(flg==pos){temp->data=data;return true;} else{return false;}
}
//清空链表
bool clearList(LNode* head){//入参判断if(NULL==head ){
#if DEBUG_PRINTprintf("clearList()的入参为空\n");
#endifreturn false;}if(NULL==head->next){ //要判断NULL==head->next 下面temp=head->nextprintf("链表中没有数据\n");return true;}LNode * temp=head->next;LNode *P=head;while (temp!=NULL){P=temp;temp=temp->next;free(P);head->data--;}head->next=NULL;return true;}//销毁链表
bool destroyList(LNode** head){//入参判断if(NULL==head || NULL==*head){
#if DEBUG_PRINTprintf("destroyList()的入参为空\n");
#endifreturn false;}clearList(*head);free(*head);(*head)=NULL;return true;
}//打印链表
bool printList(LNode* head){//入参检查if(NULL==head){
#if DEBUG_PRINTprintf("length()的入参为空\n");
#endifreturn false;}if(NULL==head->next){printf("表为空\n");return true;}LNode *temp=head->next;while (temp){printf("%d ",temp->data);temp=temp->next;}printf("\n");return true;
}

main.c测试功能

文件名:main.c
#include "link_list.h"int main(){LNode *head;initList(&head);printf("head=%p\n",head);printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));printf("----------------------------\n");//测试头插insert(head,100);insert(head,200);insert(head,300);printList(head);printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));//300 200 100printf("----------------------------\n");//测试尾插append(head,400);append(head,500);append(head,600);printList(head);printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));//300 200 100 400 500 600printf("----------------------------\n");//测试插入链表指定位置insertAt(head,333,1);insertAt(head,444,0);insertAt(head,555,8);//最后一个插入insertAt(head,666,10);//报错///insertAt()的插入位置不合理printList(head);//444 300 333 200 100 400 500 600 555printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));printf("----------------------------\n");//链表删除元素头删delete(head);delete(head);printList(head);//333 200 100 400 500 600 555printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));printf("----------------------------\n");//删除链表元素尾删deleteTail(head);printList(head);//333 200 100 400 500 600printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));//length=6printf("----------------------------\n");//链表中查找指定位置元素LNode *N=NULL;searchAt(head,-1);//位置不合理N=searchAt(head,6);//位置不合理N=searchAt(head,5);//查找数据:600if(N){printf("查找数据:%d\n",N->data);} else{printf("没查到\n");}printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));printf("----------------------------\n");//修改链表指定位置元素modify(head,777,0);modify(head,888,6);//modify()的修改位置不合理printList(head);//777 200 100 400 500 600printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));printf("----------------------------\n");//链表删除指定位置元素deleteAt(head,0);printList(head);//200 100 400 500 600printf("Empty=%d\n",isEmpty(head));printf("length=%d\n",length(head));printf("----------------------------\n");//清空链表clearList(head);printf("head=%p\n",head);//head=0000000000B11450printf("head->next=%p\n",head->next);//head->next=0000000000000000printList(head);//表为空printf("Empty=%d\n",isEmpty(head));//Empty=1printf("length=%d\n",length(head));//length=0printf("----------------------------\n");//销毁destroyList(&head);printf("head=%p\n",head);//head=0000000000000000printf("----------------------------\n");
}

总结

链表是一种常见的数据结构,在实际应用中有着广泛的应用。本文介绍了链表的定义、实现、操作、测试等功能。

链表的实现主要是定义链表节点的结构,然后实现链表的操作函数。链表的操作函数包括:初始化链表、链表是否为空、链表长度、链表头部插入元素、链表尾部插入元素、插入链表指定位置、链表删除元素头删、链表删除指定位置元素、删除链表元素尾删、链表中查找指定位置元素、修改链表指定位置元素、清空链表、销毁链表、打印链表。

链表的操作函数都有相应的注释,可以很方便地理解各个函数的作用。

链表的测试代码主要是对链表的操作函数进行测试 ,可以作为学习链表的入门代码。

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

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

相关文章

python爬虫:实现程序模拟点击搜索等任务,爬取动态网页

引言: 爬虫也被称为网络蜘蛛(Spider),是一种自动化的软件程序,能够在互联网上漫游,按照一定的规则和算法抓取数据。 爬虫技术广泛应用于搜索引擎、 数据挖掘 、信息提取等领域,是互联网技术的重要组成部分。 摘要: 作为爬虫的初学者,网页越简单越好,因为网页的结构…

正点原子rk3588烧录linux和安卓镜像

1、烧录 Linux buildroot 系统镜像 1.1 进入 Loader 模式&#xff1a; 按住开发板上的 V&#xff08;音量&#xff09;按键不松&#xff0c;给开发板 上电或复位&#xff0c;此时烧录工具会提示&#xff1a;发现一个 LOADER 设备&#xff0c;表示开发板此时已经处于 Loader 模…

【爆肝34万字】从零开始学Python第2天: 判断语句【入门到放弃】

目录 前言判断语句True、False简单使用作用 比较运算符引入比较运算符的分类比较运算符的结果示例代码总结 逻辑运算符引入逻辑运算符的简单使用逻辑运算符与比较运算符一起使用特殊情况下的逻辑运算符 if 判断语句引入基本使用案例演示案例补充随堂练习 else 判断子句引入else…

Node.js 事件循环的工作流程二

在每个tick的过程中&#xff0c;如何判断是否有事件需要处理 在 Node.js 的事件循环中&#xff0c;每个循环迭代称为一个 "tick"。在每个 tick 过程中&#xff0c;事件循环需要判断是否有事件需要处理。这个过程主要依赖于检查各个阶段的队列是否有待处理的回调函数…

第3章:Electron的核心概念(2)

3.4 预加载脚本 预加载脚本在渲染进程加载前执行&#xff0c;允许在渲染器上下文中暴露自定义 API&#xff0c;并提供与主进程安全通信的桥梁。使用预加载脚本可以提高应用的安全性&#xff0c;尤其是在启用了 contextIsolation 的情况下。 3.4.1 创建预加载脚本 预加载脚本…

【Docker Compose】掌握容器资源管理:高效限制CPU与内存使用

【Docker Compose】掌握容器资源管理:高效限制CPU与内存使用 一、Docker Compose 介绍1.1 Docker Compose简介1.2 Docker Compose V2简介1.3 Docker Compose V1与V2版本区别1.4 docker-compose.yaml部署文件介绍二、检查本地docker环境2.1 本地环境规划2.2 检查docker版本2.3 …

43.三倍游戏

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/390 题目描述 三倍游戏是一种单人游戏。玩…

基于51单片机心形LED流水灯电路原理图、PCB和源程序(SCH、PCB源文件)

资料下载地址&#xff1a;基于51单片机心形LED流水灯电路原理图、PCB和源程序&#xff08;SCH、PCB源文件&#xff09; 1、单片机心形LED流水灯功能说明&#xff1a; 单片机&#xff1a;无论是散件还是成品&#xff0c;单片机里面都烧录有LED 流水灯的程序&#xff0c;装上单片…

TCP重传机制

TCP重传机制是为了确保数据可靠传输而设计的&#xff0c;当传输的数据包丢失或损坏时&#xff0c;TCP会重新发送这些数据包。TCP重传主要有以下几种方式&#xff1a; 超时重传&#xff08;Timeout Retransmission&#xff09;&#xff1a; 当发送方发送一个数据包后&#xff…

【Promise】聊聊任务队列

历史小剧场 现实是残酷的&#xff0c;而今这个世界&#xff0c;要活下去&#xff0c;必死需要更大的勇气。 但崇祯的死&#xff0c;并非懦弱&#xff0c;而是一种态度&#xff0c;负责人的态度。 我说过&#xff0c;所谓王朝&#xff0c;跟公司单位差不多&#xff0c;单位出了事…

fly_bid项目

Ncurses库&#xff1a; 提供了创建窗口界面&#xff0c;移动光标&#xff0c;产生颜色&#xff0c;处理键盘按键功能问题等功能。 vim界面&#xff0c;内核配置界面&#xff08;make menuconfig&#xff09; #include<stdio.h> #include<curses.h>int main(int …

【UE 网络】RPC远程过程调用 入门篇

目录 0 引言1 RPC基本概念1.1 定义1.2 分类 2 RPC的使用2.1 Client RPC2.2 Server RPC2.3 Multicast RPC &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;UE虚幻引擎专栏&#x1f4a5; 标题&#xff1a;【UE 网络】RPC远程过程调用 入门篇❣️ 寄语…

(七)React:useEffect的理解和使用

1. useEffect的概念理解 useEffect是一个React Hook函数&#xff0c;用于React组件中创建不是由事件引起而是由渲染本身引起的操作&#xff0c;比如发送AJAX请求&#xff0c;更改DOM等等 说明&#xff1a;上面的组件中没有发生任何的用户事件&#xff0c;组件渲染完毕之后就需…

Modbus TCP与TCP/IP协议间的差异与应用场景

Modbus TCP概述 Modbus协议简介 Modbus是一种专为工业自动化系统设计的通信协议&#xff0c;采用主从模式&#xff0c;即一个主设备&#xff08;通常是计算机或可编程逻辑控制器&#xff09;与多个从设备&#xff08;如传感器、执行器等&#xff09;进行通信。Modbus协议具有…

项目优化方案之---实现单设备登录限制

对于一些付费会员或者一些商业项目&#xff0c;为了保证单个用户的账号权益不会被滥用&#xff0c;并且提高系统的安全性&#xff0c;我们会限制单个账号在同一时间内只能有一台设备登录&#xff0c; 来给系统添加共享账号的检测能能力 这里是根据jwt实现的&#xff0c;要实现…

K8S集群进行分布式负载测试

使用K8S集群执行分布式负载测试 本教程介绍如何使用Kubernetes部署分布式负载测试框架&#xff0c;该框架使用分布式部署的locust 产生压测流量&#xff0c;对一个部署到 K8S集群的 Web 应用执行负载测试&#xff0c;该 Web 应用公开了 REST 格式的端点&#xff0c;以响应传入…

初探Xcode工具

初探Xcode工具 Xcode是苹果公司为Mac OS X和iOS平台开发软件的集成开发环境&#xff08;IDE&#xff09;。作为苹果开发者的首选工具&#xff0c;Xcode提供了一系列强大的功能&#xff0c;帮助开发者设计、编写、调试和发布应用程序。本文将对Xcode进行初步探索&#xff0c;介…

【吴恩达深度学习笔记系列】Logistic Regression 【理论】

Binary Classification: Logistic Regression: y ^ σ ( w T x b ) \hat{y}\sigma{(w^T xb)} y^​σ(wTxb) using sigmoid function σ 1 1 e − z \sigma \frac{1}{1e^{-z}} σ1e−z1​. 【torch.sigmoid(x)】 Sigmoid ( x ) 1 1 e − x \text{Sigmoid}(x)\frac{1}{…

综合评价 | 基于组合博弈赋权的物流系统综合评价(Matlab)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 综合评价 | 基于组合博弈赋权的物流系统综合评价&#xff08;Matlab&#xff09; 组合博弈赋权&#xff08;Weighted Sum&#xff09;是一种常见的多目标决策方法&#xff0c;用于将多个目标指标进行综合评估和权衡…

Spring Boot中的国际化配置

Spring Boot中的国际化配置 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot应用中实现国际化配置&#xff0c;使得应用能够轻松…