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;}
}

总体跟链表类似

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

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

相关文章

【ArcGIS微课1000例】0141:提取多波段影像中的单个波段

文章目录 一、波段提取函数二、加载单波段导出问题描述:如下图所示,img格式的时序NDVI数据有24个波段。现在需要提取某一个波段,该怎样操作? 一、波段提取函数 首先加载多波段数据。点击【窗口】→【影像分析】。 选择需要处理的多波段影像,点击下方的【添加函数】。 在多…

css3 svg制作404页面动画效果HTML源码

源码介绍 css3 svg制作404页面动画效果HTML源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果 效果预览 源码如下 <!doctype html> <html> <head> <meta charse…

R语言学习笔记之高效数据操作

一、概要 数据操作是R语言的一大优势&#xff0c;用户可以利用基本包或者拓展包在R语言中进行复杂的数据操作&#xff0c;包括排序、更新、分组汇总等。R数据操作包&#xff1a;data.table和tidyfst两个扩展包。 data.table是当前R中处理数据最快的工具&#xff0c;可以实现快…

利用Qt5.15.2编写Android程序时遇到的问题及解决方法

文章目录 背景1.文件读写 背景 目前我用的是Qt5.15.2来编写Qt程序&#xff0c;环境的配置看我这篇文章【Qt5.15.2配置Android开发环境】 项目中的一些配置的截图&#xff1a; 1.文件读写 假如直接用 QFileDialog::getExistingDirectory来获取路径的话&#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将围绕“机械设计”…

leetcode刷题记录(一百)——121. 买卖股票的最佳时机

&#xff08;一&#xff09;问题描述 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09;121. 买卖股票的最佳时机 - 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票&#xff0c;并…

亲测有效!解决PyCharm下PyEMD安装报错 ModuleNotFoundError: No module named ‘PyEMD‘

解决PyCharm下PyEMD安装报错 PyEMD安装报错解决方案 PyEMD安装报错 PyCharm下通过右键自动安装PyEMD后运行报错ModuleNotFoundError: No module named ‘PyEMD’ 解决方案 通过PyCharm IDE python package搜索EMD-signal&#xff0c;选择版本后点击“install”执行安装

上海亚商投顾:沪指冲高回落 大金融板块全天强势 上海亚商投

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一&#xff0e;市场情绪 市场全天冲高回落&#xff0c;深成指、创业板指午后翻绿。大金融板块全天强势&#xff0c;天茂集团…

【unity游戏开发之InputSystem——02】InputAction的使用介绍(基于unity6开发介绍)

文章目录 前言一、InputAction简介1、InputAction是什么&#xff1f;2、示例 二、监听事件started 、performed 、canceled1、启用输入检测2、操作监听相关3、关键参数 CallbackContext4、结果 三、InputAction参数相关1、点击齿轮1.1 Actions 动作&#xff08;1&#xff09;动…

ubuntu22安装issac gym记录

整体参考&#xff1a;https://blog.csdn.net/Yakusha/article/details/144306858 安装完成后的整体版本信息 ubuntu&#xff1a;22.04内核&#xff1a;6.8.0-51-generic显卡&#xff1a;NVIDIA GeForce RTX 3050 OEM显卡驱动&#xff1a;535.216.03cuda&#xff1a;12.2cudnn&…

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到 这次在windows的WSL2中遇到了一个非常奇怪的错误&#xff0c;就是 CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):Could NOT find BLAS (missing: BLAS_LIBRAR…

15天基础内容-5

day13 【String类、StringBuilder类】 主要内容 String类常用方法【重点】 String类案例【重点】 StringBuilder类【重点】 StringBuilder类常用方法【重点&#xff1a; append】 StringBuilder类案例【理解】 第一章String类 1.1 String类的判断方法 String类实现判断功能…

CommonAPI学习笔记-1

CommonAPI学习笔记-1 一. 整体结构 CommonAPI分为两层&#xff1a;核心层和绑定层&#xff0c;使用了Franca来描述服务接口的定义和部署&#xff0c;而Franca是一个用于定义和转换接口的框架&#xff08;https://franca.github.io/franca/&#xff09;。 ​ 核心层和通信中间…

单片机基础模块学习——DS18B20温度传感器芯片

不知道该往哪走的时候&#xff0c;就往前走。 一、DS18B20芯片原理图 该芯片共有三个引脚&#xff0c;分别为 GND——接地引脚DQ——数据通信引脚VDD——正电源 数据通信用到的是1-Wier协议 优点&#xff1a;占用端口少&#xff0c;电路设计方便 同时该协议要求通过上拉电阻…

Golang Gin系列-9:Gin 集成Swagger生成文档

文档一直是一项乏味的工作&#xff08;以我个人的拙见&#xff09;&#xff0c;但也是编码过程中最重要的任务之一。在本文中&#xff0c;我们将学习如何将Swagger规范与Gin框架集成。我们将实现JWT认证&#xff0c;请求体作为表单数据和JSON。这里唯一的先决条件是Gin服务器。…

< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机

原因&#xff1a; &#xff1c; OS 有关 &#xff1e; 阿里云&#xff1a;轻量应用服务器 的使用 &#xff1a;从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作&#xff1a; 查看进程&#x…

设计模式的艺术-代理模式

结构性模式的名称、定义、学习难度和使用频率如下表所示&#xff1a; 1.如何理解代理模式 代理模式&#xff08;Proxy Pattern&#xff09;&#xff1a;给某一个对象提供一个代理&#xff0c;并由代理对象控制对原对象的引用。代理模式是一种对象结构型模式。 代理模式类型较多…

K8S极简教程(4小时快速学会)

1. K8S 概览 1.1 K8S 是什么 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ 1.2 K8S核心特性 服务发现与负载均衡&#xff1a;无需修改你的应用程序即可使用陌生的服务发现机制。存储编排&#xff1a;自动挂载所选存储系统&#xff0c;包括本地存储。Secret和…

python3+TensorFlow 2.x(五)CNN

目录 CNN理解 code实现人脸识别 数据集准备&#xff1a; code实现 模型解析 结果展示 结果探讨 基于vgg16的以图搜图 数据准备 图库database 检索测试集datatest code实现 code解析 结果展示 CNN理解 卷积神经网络&#xff08;CNN&#xff09;是深度学习中最强大…

(一)HTTP协议 :请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…