初阶数据结构的实现1 顺序表和链表
顺序表和链表
- 1.线性表
- 1.1顺序表
- 1.1.1静态顺序表(不去实现)
- 1.1.2动态顺序表
- 1.1.2.1 定义程序目标
- 1.1.2.2 设计程序
- 1.1.2.3编写代码
- 1.1.2.3测试和调试代码
- 1.1.2 顺序表的问题与思考
- 1.2链表
- 1.2.1链表的概念及结构
- 1.2.1.1 定义程序目标
- 1.2.1.2 设计程序
- 1.2.1.3编写代码
- 1.1.2.3测试和调试代码
1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
相同特性
逻辑结构:人为想象出来的数据的组织形式
物理结构:数据在想象出来的数据的组织形式。
1.1顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
1.1.1静态顺序表(不去实现)
#define N 5
typedef int SLdatatype;
typedef struct SeqList {SLdatatype array [N];int size;
};
1.1.2动态顺序表
typedef int SLdatatype;
typedef struct SeqList {SLdatatype *arr;int capacity;//容量int size;//有效数据个数
}SL
1.1.2.1 定义程序目标
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef struct SeqList {SLDatatype *arr;int capacity;//容量int size;//有效数据个数
}SL;//初始化
void SLInitialize(SL*s);//销毁
void SLDestroy(SL*s );//打印顺序表
void SLPrint(SL* ps);//插入数据
//尾插
void SLPushBack(SL*s, SLDatatype x);//头插
void SLPushFront(SL*s, SLDatatype x);//尾删
void SLPopBack(SL* s);//头删
void SLPopFront(SL* s);//在指定位置插入数据
void SLInsert(SL* s, SLDatatype x, int pos);//在指定位置删除数据
void SLErase(SL* s,int pos);//查找数据
int SLFind(SL* s, SLDatatype x);
1.1.2.2 设计程序
面向程序员自身的,能实现包括顺序表的结构定义、初始化、插入、删除、查找、遍历、排序等操作
1.1.2.3编写代码
void SLInitialize(SL* ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLCheckCapacity(SL* ps)
{//判断空间是否充足if (ps->size == ps->capacity){//增容//若capacity为0,给个默认值,否则×2倍int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDatatype* tmp = (SLDatatype*)realloc(ps->arr, NewCapacity * sizeof(SLDatatype));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = NewCapacity;}
}void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}void SLPushBack(SL*ps, SLDatatype x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}void SLPushFront(SL* ps, SLDatatype x)
{assert(ps);SLCheckCapacity(ps);//数据整体后移for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i-1];}ps->arr[0] = x;ps->size++;
}void SLPopBack(SL* ps)
{assert(ps && ps->size);ps->size--;
}
void SLPopFront(SL* ps)
{assert(ps && ps->size);for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}void SLInsert(SL* ps, SLDatatype x, int pos)
{assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);for (int i = ps->size; i >pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[ps->size] = x;ps->size++;}void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size&& ps->size);for (int i=pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i+1];}ps->size--;
}int SLFind(SL* ps, SLDatatype x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x)return i;}return -1;
}
1.1.2.3测试和调试代码
#include"Seqlist.h"
void SLtest01()
{SL s;SLInitialize(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPushBack(&s, 5);SLPushBack(&s, 6);/*SLPushBack(NULL , 6);*/SLPushFront(&s, 1);SLPushFront(&s, 2);SLPushFront(&s, 3);SLPushFront(&s, 4);SLPrint(&s); //4 3 2 1SLPopBack(&s);SLPrint(&s);SLPopBack(&s);SLPrint(&s);SLPopBack(&s);SLPrint(&s);SLPopBack(&s);SLPrint(&s);SLPopFront(&s);SLPrint(&s);SLPopFront(&s);SLPrint(&s);SLPopFront(&s);SLPrint(&s);SLPopFront(&s);SLPrint(&s);SLPopFront(&s);SLPrint(&s);SLInsert(&s, 11, 0);SLPrint(&s);SLInsert(&s, 22, s.size);SLPrint(&s);SLInsert(&s, 33, 1);SLPrint(&s);SLDestroy(&s);
}int main()
{SLtest01();return 0;
}

1.1.2 顺序表的问题与思考
- 中间/头部的插入删除,时间复杂度为O(N)
- 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
- 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们
再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
思考:如何解决以上问题呢?下面给出了链表的结构来看看。
1.2链表
1.2.1链表的概念及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链
接次序实现的 。
1.2.1.1 定义程序目标
实现
define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDataType;//定义结点结构;
typedef struct SListNode {SLTDataType data;struct SListNode* next;
}SLTNode;//链表的打印
void SLTPrint(SLTNode*);
//申请新结点
SLTNode* SLTBuyNode(SLTDataType);
//尾插
void SLTPushBack(SLTNode**, SLTDataType);
//头插
void SLTPushFront(SLTNode** , SLTDataType );//删除//尾删
void SLTPopBack(SLTNode**);
//头删
void SLTPopFront(SLTNode**);//查找
SLTNode* SLTFind(SLTNode*, SLTDataType);//在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos);//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos);//销毁链表
void SListDestroy(SLTNode** pphead);
1.2.1.2 设计程序
面向程序员自身的,能实现包括链表的结构定义、初始化、插入、删除、查找、遍历、排序等操作
1.2.1.3编写代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));if (node == NULL){perror("malloc fail");exit(1);}node->data = x;node->next = NULL;return node;
}void SLTPushBack(SLTNode**pphead, SLTDataType x)
{//申请新结点SLTNode*NewNode = SLTBuyNode(x);if (*pphead == NULL){*pphead = NewNode;}//尾结点->新结点//找尾结点else{SLTNode* pcur = *pphead;while (pcur->next){pcur = pcur->next;}pcur->next = NewNode;}
}void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);//申请新结点SLTNode* NewNode = SLTBuyNode(x);//进行头插NewNode->next = *pphead;*pphead = NewNode;
}void SLTPopBack(SLTNode** pphead)
{//链表为空不可以删除assert(pphead && *pphead);//处理链表只有一个结点的情况if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{//找prev和ptailSLTNode* ptail = *pphead;SLTNode* prev = NULL;while (ptail->next){prev = ptail;ptail = ptail->next;}prev->next = NULL;free(ptail);ptail = NULL;}
}void SLTPopFront(SLTNode** pphead)
{//链表为空不可以删除assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = NULL;*pphead = next;
}SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{SLTNode* pcur = phead;while (pcur){if (pcur->data == x){return pcur;}else{pcur = pcur->next;}}return NULL;
}void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);if (*pphead == pos)SLTPushBack(pphead, x);else{SLTNode* prev = *pphead;SLTNode* NewNode = SLTBuyNode(x);while (prev->next != pos){prev = prev->next;}prev->next = NewNode;NewNode->next = pos;}
}void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* NewNode = SLTBuyNode(x);NewNode->next = pos->next;pos->next = NewNode;
}void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead&&*pphead);assert(pos);if (*pphead = pos)SLTPopBack(pphead);else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}void SLTEraseAfter(SLTNode* pos)
{assert(pos && pos->next);SLTNode* del = pos->next;pos->next = pos->next->next;free(del);del = NULL;
}void SListDestroy(SLTNode** pphead)
{SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}
1.1.2.3测试和调试代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"void SListTest01()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);//1->2->3->4->NULLSLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist); //4->3->2->1->NULLSLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTNode* find = SLTFind(plist, 4);if (find == NULL){printf("未找到!\n");}else{printf("找到了!\n");}SLTInsert(&plist, plist, 11);//4->3->2->11->1->NULLSLTInsertAfter(plist, 11);SLTPrint(plist);1->11->2->3->4->NULLSLTErase(&plist, plist);// 1->2->3->NULLSLTEraseAfter(plist);SLTPrint(plist);SListDestroy(&plist);SLTPrint(plist);
}
int main()
{SListTest01();return 0;
}

相关文章:
初阶数据结构的实现1 顺序表和链表
顺序表和链表 1.线性表1.1顺序表1.1.1静态顺序表(不去实现)1.1.2动态顺序表1.1.2.1 定义程序目标1.1.2.2 设计程序1.1.2.3编写代码1.1.2.3测试和调试代码 1.1.2 顺序表的问题与思考 1.2链表1.2.1链表的概念及结构1.2.1.1 定义程序目标1.2.1.2 设计程序1.…...
破解反爬虫策略 /_guard/auto.js(一) 原理
背景 当用代码或者postman访问一个网站的时候,访问他的任何地址都会返回<script src"/_guard/auto.js"></script>,但是从浏览器中访问显示的页面是正常的,这种就是网站做了反爬虫策略。本文就是带大家来破解这种策略&…...
40.简易频率计(基于等精度测量法)(3)
(1)BCD8421码:十进制数字转换成BCD8421码的方法 补零:你需要显示多少位数字,就在前面补上四倍的位宽。比如你要显示一个十进制8位的数字,就在前面补上8*432个零。判断:判断补零部分显示的十进制…...
关于Centos停更yum无法使用的解决方案
最近在使用Centos7.9系统时候,发现yum仓库无法进行安装软件包了,官方说2024年6月30日进行停更,停更后无法提供对应的软件服务。 我在使用yum安装包的时候发现确实不能使用官方服务了: CentOS停更的影响 CentOS停止更新之后&#…...
插画感言:成都亚恒丰创教育科技有限公司
插画感言:笔触间的灵魂对话 在这个快节奏、高压力的时代,我们时常在寻找那些能够触动心灵、让灵魂得以片刻栖息的角落。而插画,这一融合了艺术与情感的独特形式,便如同一股清泉,缓缓流淌进每个人的心田,以…...
【算法】数组中的第K个最大元素
难度:中等 题目: 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题…...
Perl 语言的特点
Perl 语言入门学习可以涵盖多个方面,包括其特点、基本语法、高级特性以及学习资源和社区支持等。以下是一个详细的入门学习指南: 一、Perl 语言的特点 文本处理能力强:Perl 提供了丰富的字符串处理函数和正则表达式的支持,非常适…...
NLP教程:1 词袋模型和TFIDF模型
文章目录 词袋模型TF-IDF模型词汇表模型 词袋模型 文本特征提取有两个非常重要的模型: 词集模型:单词构成的集合,集合自然每个元素都只有一个,也即词集中的每个单词都只有一个。 词袋模型:在词集的基础上如果一个单词…...
【开源 Mac 工具推荐之 2】洛雪音乐(lx-music-desktop):免费良心的音乐平台
旧版文章:【macOS免费软件推荐】第6期:洛雪音乐 Note:本文在旧版文章的基础上,新更新展示了一些洛雪音乐的新功能,并且描述更为详细。 简介 洛雪音乐(GitHub 名:lx-music-desktop )…...
AMEYA360:思瑞浦推出汽车级理想二极管ORing控制器TPS65R01Q
聚焦高性能模拟芯片和嵌入式处理器的半导体供应商思瑞浦3PEAK(股票代码:688536)发布汽车级理想二极管ORing控制器TPS65R01Q。 TPS65R01Q拥有20mV正向调节功能,降低系统损耗。快速反向关断(Typ:0.39μs),在电池反向和各种汽车电气瞬…...
简约的悬浮动态特效404单页源HTML码
源码介绍 简约的悬浮动态特效404单页源HTML码,页面简约美观,可以做网站错误页或者丢失页面,将下面的代码放到空白的HTML里面,然后上传到服务器里面,设置好重定向即可 效果预览 完整源码 <!DOCTYPE html> <html><head><meta charset="utf-8&q…...
Golang 创建 Excel 文件
经常会遇到需要导出数据报表的需求,除了可以通过 encoding/csv 导出 CSV 以外,还可以使用 https://github.com/qax-os/excelize 导出 xlsx 等格式的 excel,下面封装了一个方法,支持多 sheet 的 excel 数据生成,导出按需…...
探索GitHub上的两个革命性开源项目
在数字世界中,总有一些项目能够以其创新性和实用性脱颖而出,吸引全球开发者的目光。今天,我们将深入探索GitHub上的两个令人惊叹的开源项目:Comic Translate和GPTPDF,它们不仅改变了我们处理信息的方式,还极…...
SpringBoot框架学习笔记(三):Lombok 和 Spring Initailizr
1 Lombok 1.1 Lombok 介绍 (1)Lombok 作用 简化JavaBean开发,可以使用Lombok的注解让代码更加简洁Java项目中,很多没有技术含量又必须存在的代码:POJO的getter/setter/toString;异常处理;I/O…...
【ASP.NET网站传值问题】“object”不包含“GetEnumerator”的公共定义,因此 foreach 语句不能作用于“object”类型的变量等
问题一:不允许遍历 原因:实体未强制转化 后端: ViewData["CateGroupList"] grouplist; 前端加上:var catelist ViewData["CateGroupList"] as List<Catelogue>; 这样就可以遍历catelist了 问题二:…...
Stateflow中的状态转换表
状态转换表是表达顺序模态逻辑的另一种方式。不要在Stateflow图表中以图形方式绘制状态和转换,而是使用状态转换表以表格格式表示模态逻辑。 使用状态转换表的好处包括: 易于对类列车状态机进行建模,其中模态逻辑涉及从一个状态到其邻居的转换…...
结合Redis解决接口幂等性问题
结合Redis解决接口幂等性问题 引言正文收获 引言 该问题产生背景是根据需求描述,要求对已发布的课程能进行编辑修改,并且要求能进行回滚。 幂等性问题描述:对同一个接口并发请求产生的结果是不变的。 Get 请求以及 Delete 请求天然保证幂等…...
2024算力基础设施安全架构设计与思考(免费下载)
算网安全体系是将数据中心集群、算力枢纽、一体化大数据中心三个层级的安全需求进行工程化解耦,从国家安全角度统筹设计,通过安全 服务化方式,依托威胁情报和指挥协同通道将三层四级安全体系串联贯通,达成一体化大数据安全目标。 …...
ExoPlayer架构详解与源码分析(15)——Renderer
系列文章目录 ExoPlayer架构详解与源码分析(1)——前言 ExoPlayer架构详解与源码分析(2)——Player ExoPlayer架构详解与源码分析(3)——Timeline ExoPlayer架构详解与源码分析(4)—…...
网络安全-等级保护制度介绍
一、等保发展历程 (1)1994国务院147号令 第一次提出等级保护概念,要求对信息系统分等级进行保护 (2)1999年GB17859 国家强制标准发布,信息系统等级保护必须遵循的法规 (3)2005年公安…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
