当前位置: 首页 > article >正文

C语言学习强化

前言

数据的逻辑结构包括:

常见数据结构:

线性结构:数组、链表、队列、栈

树形结构:树、堆

图形结构:图 

一、链表

链表是物理位置不连续,逻辑位置连续

链表的特点:

1.链表没有固定的长度,可以自由增加节点

2.链表可以快速插入和删除数据

链表和数组的优劣

1.数组查找方便,尾部插入数据效率高,但在开头和中间插入数据效率低,需要移位

2.链表查找麻烦,无论在什么位置插入或删除数据效率都高

1.链表的创建与死亡

(1)定义链表中节点的结构

//在实现链式表之前,先确定表中某一个节点类型
typedef struct MyNode
{int data;struct MyNode *pNext;
}NODE;

data为数据域,pNext为指针域,指向下一个节点 

(2)定义链表结构

//单向链表的类型定义
typedef struct LinkList
{NODE* pHead;		//链表的头节点NODE* pEnd;			//链表的尾节点int length;			//链表的长度
}LL;

pHead指向链表的头节点,pEnd指向链表的尾节点,length来记录链表的长度

(3)创建单链表

//创建单链表
LL* List_Init()
{LL* pTemp = (LL*)malloc(sizeof(LL));if (NULL == pTemp){return NULL;}else{pTemp->pHead = NULL;pTemp->pEnd = NULL;pTemp->length = 0;return pTemp;}
}

链表初始化,malloc动态分配内存,将头节点、尾节点、长度初始化后,返回链表的首地址。

(4)创建链表中的一个节点

//创建链表的一个节点
NODE* NODE_Init(int data)
{NODE* pTemp = (NODE*)malloc(sizeof(NODE));if (NULL == pTemp){return NULL;}else{pTemp->pNext = NULL;pTemp->data = data;return pTemp;}
}

创建链表中的一个节点,把数据放入节点中,但指向下一个节点的指针仍为空指针,也暂时还没有指针指向该节点,也就是说该节点目前还没有与链表建立联系

(5)链表的死亡

//链表的死亡
void List_Dele(LL **pList)
{if (NULL == *pList){printf("链表不存在\n");return;}NODE* pTemp = NULL;			//借用临时变量循环遍历链表中的每个节点再进行删除while ((*pList)->pHead)		//当头节点为空指针时,链表节点遍历完成{pTemp = (*pList)->pHead;		//暂存头节点的地址(*pList)->pHead = (*pList)->pHead->pNext;			//头节点移至下一节点free(pTemp);			//释放节点所占内存}free(*pList);			//释放链表所占内存*pList = NULL;          //将指向链表的指针赋值为空指针
}

利用二级指针可以改变一级指针的内容

int main()
{LL* pList = List_Init();if (NULL == pList){printf("创建失败\n");}List_Dele(&pList);return 0;
}

这里main函数给List_Dele传参时是取了链表指针的地址,于是在函数中,就能修改链表指针的内容

2.链表的插入

(1)链表尾部添加元素

//在链表尾部添加元素
void List_append(LL* pList, int val)
{if (NULL == pList){printf("链表不存在,添加失败\n");return;}NODE* pTemp = NODE_Init(val);if (NULL == pTemp){printf("节点创建失败\n");}if (NULL == pList->pHead)        //检查是否为空链表{pList->pHead = pList->pEnd = pTemp;        //空链表则头尾指针同时指向该新增元素}else{pList->pEnd->pNext = pTemp;            //非空链表情况pList->pEnd = pTemp;}pList->length++;                        //链表长度加1
}

详细分析见注释内容 

(2)链表中插入元素

//链表中插入元素
void List_insert(LL* pList, int idx, int val)
{if (NULL == pList){printf("链表不存在,添加失败\n");return;}NODE* pTemp = NODE_Init(val);if (NULL == pTemp){printf("节点创建失败,添加失败\n");}if (idx >= pList->length)            //如果索引超出长度范围,元素添加至尾部		{pList->pEnd->pNext = pTemp;pList->pEnd = pTemp;}else if (idx <= 0)                    //如果索引小于等于0,元素添加至开头{pTemp->pNext = pList->pHead;pList->pHead = pTemp;}else                                    //索引不在首尾处{NODE* pInsertNode = pList->pHead;        //从头节点开始迭代for (int i = 0; i < idx - 1; i++)         //指针迭代一次次往后指{pInsertNode = pInsertNode->pNext;    //一直迭代到指向要插入索引的前面}pTemp->pNext = pInsertNode->pNext;        //先让插入元素指向索引位置元素pInsertNode->pNext = pTemp;                //再让索引位置前的元素指向插入元素}pList->length++;
}

详细分析见注释内容 

(3)链表中删除元素

//删除单个元素
void List_deleNode(LL* pList, int idx)
{if (NULL == pList || 0 == pList->length){printf("链表不存在,添加失败\n");return;}if (idx < 0 || idx >= pList->length){printf("删除位置不存在\n");return;}NODE* pTemp = NULL;if (idx == 0)            //删除位置为开头{pTemp = pList->pHead;pList->pHead = pList->pHead->pNext;}else                    //删除位置为中间或尾部{NODE* pCurNode = pList->pHead;for (int i = 0; i < idx - 1; i++){pCurNode = pCurNode->pNext;        //迭代至指向删除元素的上一个}pTemp = pCurNode->pNext;pCurNode->pNext = pTemp->pNext;if (pCurNode->pNext == NULL){pList->pEnd = pCurNode;}}free(pTemp);pList->length--;
}

二、栈和队列

操作受限的线性表

栈的特点:先进后出

队列的特点:先进先出

1.栈

操作:出栈、入栈、得到栈顶元素、判断栈满或栈空

通过顺序表来实现

#include <stdio.h>
#include <stdlib.h>
#define STACK_LEN 10typedef struct MyStack
{int dataArr[STACK_LEN];int top;
}STACK;//创建
STACK* Stack_Init()
{STACK* pStack = (STACK*)malloc(sizeof(STACK));if (NULL == pStack){printf("栈创建失败\n");return NULL;}pStack->top = 0;return pStack;
}//判断栈是否满
int FullStack(STACK* pStack)
{if (pStack->top >= STACK_LEN){return 1;}return 0;
}//判断栈是否空
int EmptyStack(STACK* pStack)
{if (pStack->top == 0){return 1;}return 0;
}
//入栈
void Stack_push(STACK* pStack, int val)
{if (NULL == pStack){printf("栈不存在,入栈失败\n");return;}if (FullStack(pStack) == 1){printf("栈已满,不能入栈\n");return;}pStack->dataArr[pStack->top++] = val;
}//出栈
void Stack_pop(STACK* pStack)
{if (NULL == pStack){printf("栈不存在,入栈失败\n");return;}if (EmptyStack(pStack) == 1){printf("栈为空,不能入栈\n");return;}pStack->top--;
}//获取栈顶元素
int Stack_top(STACK* pStack)
{//栈为空,或栈不存在都会报错return pStack->dataArr[pStack->top - 1];
}//删除栈
void Stack_clear(STACK** pStack)
{if (NULL != *pStack){free(*pStack);*pStack = NULL;}
}int main()
{STACK* pStack = NULL;pStack = Stack_Init();Stack_clear(&pStack);return 0;
}

2.队列

操作:出栈、入栈、得到队头、得到队尾

通过链式表来实现

#include <stdio.h>
#include <stdlib.h>typedef struct MyNode
{int data;struct MyNode* pNext;
}NODE;typedef struct MyQueue
{NODE* pHead;		NODE* pEnd;			
}QUEUE;QUEUE* Queue_Init()
{QUEUE* pTemp = (QUEUE*)malloc(sizeof(QUEUE));if (NULL == pTemp){printf("队列创建失败\n");return NULL;}else{pTemp->pHead = NULL;pTemp->pEnd = NULL;return pTemp;}
}NODE* NODE_Init(int data)
{NODE* pTemp = (NODE*)malloc(sizeof(NODE));if (NULL == pTemp){printf("节点创建失败\n");return NULL;}else{pTemp->pNext = NULL;pTemp->data = data;return pTemp;}
}//入队
void Queue_push(QUEUE* pQue, int val)
{if (NULL == pQue){printf("链表不存在,添加失败\n");return;}NODE* pTemp = NODE_Init(val);if (NULL == pQue->pHead){pQue->pHead = pQue->pEnd = pTemp;}else{pQue->pEnd->pNext = pTemp;pQue->pEnd = pTemp;}
}//出队
void Queue_pop(QUEUE* pQue)
{if (NULL == pQue || NULL == pQue->pHead){printf("队列不存在\n");return;}NODE* pTemp = NULL;pTemp = pQue->pHead;pQue->pHead = pQue->pHead->pNext;if (NULL == pQue->pHead)pQue->pEnd = NULL;
}int Queue_front(QUEUE* pQue)
{return pQue->pHead->data;
}int Queue_back(QUEUE* pQue)
{return pQue->pEnd->data;
}void Queue_clear(QUEUE** pQue)
{if (NULL != *pQue){free(*pQue);*pQue = NULL;}
}

总体跟链表类似

相关文章:

C语言学习强化

前言 数据的逻辑结构包括&#xff1a; 常见数据结构&#xff1a; 线性结构&#xff1a;数组、链表、队列、栈 树形结构&#xff1a;树、堆 图形结构&#xff1a;图 一、链表 链表是物理位置不连续&#xff0c;逻辑位置连续 链表的特点&#xff1a; 1.链表没有固定的长度…...

反馈驱动、上下文学习、多语言检索增强等 | Big Model Weekly 第55期

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 01 A Bayesian Approach to Harnessing the Power of LLMs in Authorship Attribution 传统方法严重依赖手动特征&#xff0c;无法捕捉长距离相关性&#xff0c;限制了其有效性。最近的研究利用预训练语言模型的…...

Redis 详解

简介 Redis 的全称是 Remote Dictionary Server&#xff0c;它是一个基于内存的 NoSQL&#xff08;非关系型&#xff09;数据库&#xff0c;数据以 键值对 存储&#xff0c;支持各种复杂的数据结构 为什么会出现 Redis&#xff1f; Redis 的出现是为了弥补传统数据库在高性能…...

git reset (取消暂存,保留工作区修改)

出现这种情况的背景&#xff1a;我不小心把node_modules文件添加到暂存区了&#xff0c;由于文件过大&#xff0c;导致不能提交&#xff0c;所以我想恢复之前的状态&#xff0c;但又不想把修改的代码恢复为之前的状态&#xff0c;所以使用这个命令可以只恢复暂存区的状态&#…...

C++ 自定义字面量

在C11中&#xff0c;用户自定义字面量&#xff08;User-Defined Literals&#xff09;为程序员提供了前所未有的灵活性和便利性&#xff0c;它允许我们根据自己的需求定义字面量&#xff0c;从而使代码更加直观、易读且富有表现力。 什么是用户定义字面量&#xff1f; 在C中&…...

2024年面对不确定性

24年处在了十字路口&#xff0c;面对工作、家庭、生活的责任&#xff0c;一切变得不确定了&#xff0c;量子力学给了我们新的认识世界的角度&#xff0c;不确定性才是这个世界的底色&#xff0c;我们怎么选择&#xff1f; 不停的思考 霍金在大设计书中给出了深刻的哲学思想&a…...

Coze插件开发之基于已有服务创建并上架到扣子商店

Coze插件开发之基于已有服务创建并上架到扣子商店 在应用开发中&#xff0c;需要调用各种插件&#xff0c;以快速进行开发。但有时需要调用的插件在扣子商店里没有&#xff0c;那怎么办呢&#xff1f; 今天就来带大家快速基于已有服务创建一个新的插件 简单来讲&#xff0c;就是…...

Oracle 创建用户和表空间

Oracle 创建用户和表空间 使用sys 账户登录 建立临时表空间 --建立临时表空间 CREATE TEMPORARY TABLESPACE TEMP_POS --创建名为TEMP_POS的临时表空间 TEMPFILE /oracle/oradata/POS/TEMP_POS.DBF -- 临时文件 SIZE 50M -- 其初始大小为50M AUTOEXTEND ON -- 支持…...

企业微信开发009_使用WxJava企业微信开发框架_封装第三方应用企业微信开发002_并且实现多企业授权访问---企业微信开发011

继续接上一节来贴代码: 接下来看 config部分的代码,这部分代码,系统启动的时候,就会执行,从而把配置的一些,配置读取出来,创建,针对每个企业微信的,操作service. 首先看yml配置文件中配置部分: 可以先看一下demo中: 提供了一个配置的示例,当然这个是针对 企业内部自建应用 …...

机器学习 - 初学者需要弄懂的一些线性代数的概念

一、单位矩阵 在数学中&#xff0c;单位矩阵是一个方阵&#xff0c;其主对角线上的元素全为1&#xff0c;其余元素全为0。单位矩阵在矩阵乘法中起到类似于数字1在数值乘法中的作用&#xff0c;即任何矩阵与单位矩阵相乘&#xff0c;结果仍为原矩阵本身。 单位矩阵的定义&…...

【学术会议-第五届机械设计与仿真国际学术会议(MDS 2025) 】前端开发:技术与艺术的完美融合

重要信息 大会官网&#xff1a;www.icmds.net 大会时间&#xff1a;2025年02月28日-03月02日 大会地点&#xff1a;中国-大连 会议简介 2025年第五届机械设计与仿真国际学术会议&#xff08;MDS 2025) 将于2025年02月28-3月02日在中国大连召开。MDS 2025将围绕“机械设计”…...

RabbitMQ 分布式高可用

文章目录 前言一、持久化与内存管理1、持久化机制2、内存控制1、命令行2、配置文件 3、内存换页4、磁盘控制 二、集群1、Erlang的分布式特性2、RabbitMQ的节点类型2.1、磁盘节点 (Disk Node)2.2、内存节点 (RAM Node) 3、构建集群3.1 普通集群3.2 镜像队列3.3、高可用实现方案3…...

海康工业相机 SDK对接 Hikvision

有C#基础的&#xff0c;可以参考下&#xff0c;直接上代码 BaseResult 来自于Nuget包&#xff0c;搜Rotion可以搜出来 LS.Standard.Data 海康的接口操作&#xff0c;要先引用相应的dll using MvCamCtrl.NET; using PCZD.Commons.Data.CameraModel; using PCZD.Data; using Sys…...

开发技巧,vue 中的动态组件的引用 component + is

在项目中很多时候有切换 tab 的场景&#xff0c;一般来说都是用 v-if 或者 v-show 然后根据各种条件来控制显示隐藏。 其实我们可以使用 vue 中的动态组件&#xff0c;也能实现这个效果 <!-- currentTab 改变时组件也改变 --> <component :is"currentTab"…...

MySQL 二进制安装(正式篇)

Author&#xff1a;Arsen Date&#xff1a;2025/01/24 官方参考文档&#xff1a;点击链接跳转 目录 规划下载安装管理FAQ 规划 OSMySQL Server Version备注CentOS 7.9 or Linux - Generic8.0.33(GNU libc) 2.17 下载 二进制包下载地址&#xff1a;https://downloads.mysql.…...

MongoDB 数据库备份和恢复全攻略

在当今数据驱动的时代&#xff0c;数据库的稳定运行和数据安全至关重要。MongoDB 作为一款流行的 NoSQL 数据库&#xff0c;以其灵活的文档模型和高扩展性备受青睐。然而&#xff0c;无论数据库多么强大&#xff0c;数据丢失的风险始终存在&#xff0c;因此掌握 MongoDB 的备份…...

K8S部署DevOps自动化运维平台

持续集成&#xff08;CI&#xff09; 持续集成强调开发人员提交了新代码之后&#xff0c;立刻自动的进行构建、&#xff08;单元&#xff09;测试。根据测试结果&#xff0c;我 们可以确定新代码和原有代码能否正确地集成在一起。持续集成过程中很重视自动化测试验证结果&#…...

工业相机 SDK 二次开发-Sherlock插件

本文介绍了 sherlock 连接相机时的插件使用。通过本套插件可连接海康的工业相机。 一&#xff0e;环境配置 1. 拷贝动态库 在用户安装 MVS 目录下按照如下路径 Development\ThirdPartyPlatformAdapter 找到目 录为 DalsaSherlock 的文件夹&#xff0c;根据 Sherlock 版本找到…...

分布式版本控制系统:Git

1 Git概述 Git官网&#xff1a;https://git-scm.com/ Git是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目Git易于学习&#xff0c;占地面积小&#xff0c;性能极快。它具有廉价的本地库、方便的暂存区域和多个工作流分支等特性…...

页高速缓存与缓冲区缓存的应用差异

页高速缓存&#xff08;Page Cache&#xff09;与缓冲区缓存&#xff08;Buffer Cache&#xff09;是计算机系统中用于提高数据访问性能的两种不同类型的缓存机制&#xff0c;它们的差异主要体现在以下几个方面&#xff1a; 缓存目的 页高速缓存&#xff1a;主要用于加速对磁…...

C语言编程笔记:文件处理的艺术

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一、为什么要用文件二、文件的分…...

如何编写一个MyBatis插件?

大家好&#xff0c;我是锋哥。今天分享关于【Redis为什么这么快?】面试题。希望对大家有帮助&#xff1b; 如何编写一个MyBatis插件&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 编写 MyBatis 插件需要使用 MyBatis 提供的插件接口&#xff0c;MyBa…...

验证二叉搜索树(力扣98)

根据二叉搜索树的特性&#xff0c;我们使用中序遍历&#xff0c;保证节点按从小到大的顺序遍历。既然要验证&#xff0c;就是看在中序遍历的条件下&#xff0c;各个节点的大小关系是否符合二叉搜索树的特性。双指针法和适合解决这个问题&#xff0c;一个指针指向当前节点&#…...

C语言初阶牛客网刷题—— HJ34 图片整理【难度:中等】

1. 题目描述 牛客网在线OJ链接 Lily上课时使用字母数字图片教小朋友们学习英语单词&#xff0c;每次都需要把这些图片按照大小&#xff08;ASCII码值从小到大&#xff09;排列收好。请大家给Lily帮忙&#xff0c;通过C语言解决。 输入描述&#xff1a;Lily使用的图片包括 “A…...

Golang Gin系列-7:认证和授权

在本章中&#xff0c;我们将探讨Gin框架中身份验证和授权的基本方面。这包括实现基本的和基于令牌的身份验证&#xff0c;使用基于角色的访问控制&#xff0c;应用中间件进行授权&#xff0c;以及使用HTTPS和漏洞防护保护应用程序。 实现身份认证 Basic 认证 Basic 认证是内置…...

mysql create table的用法

在MySQL中创建表的基本语法如下&#xff1a; CREATE TABLE table_name (column1 datatype,column2 datatype,column3 datatype,... );这里是一个例子&#xff0c;假设我们要创建一个名为employees的表&#xff0c;包含以下字段&#xff1a; id&#xff1a;一个整数类型的主键…...

蓝桥杯算法赛第25场月赛

前言 这些题对于我的难度有点大&#xff0c;大家感兴趣的可以来做一下&#xff0c;看一下&#xff0c;下面给大家展示一下题目 1. 桃花运走向【算法赛】 问题描述 2025 年春节&#xff0c;小明和小红兴致勃勃地去庙会玩耍。庙会上&#xff0c;一个算命先生摆摊算命&#xf…...

从介词到状语 (什么都研究一点系列)

契子 英语中介词的使用频率很高, 但在使用时本质上作为状语而成为句子成分, 没错 “本质上” 这三个字就是状语 &#x1f603; 形式上是这样: 介词 -> 状语 -> 句子 常见的介词: 时间 at, 地点 on, 原因 of, 方式 in, 伴随 with, 比较 than, 条件 if 等等 下面我们开…...

CVE-2025-0411 7-zip 漏洞复现

文章目录 免责申明漏洞描述影响版本漏洞poc漏洞复现修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 此漏洞 &#xff08;CVSS SCORE 7.0&#xff09; 允许远程攻击者绕…...

java入门笔记基础语法篇(4)

变量 在Java中&#xff0c;每个变量都有一个类型&#xff08;type&#xff09;。在声明变量时&#xff0c;变量的类型位于变量 名之前。例如&#xff1a; int days; double salary; long earthPopulation; boolean done; 在Java中&#xff0c;每个声明以分号结束。变量名必须…...