怎样提高网站访问速度,python django做的网站,网站对一个关键词做排名怎么做,四川移动网站建设每日壁纸分享#xff08;壁纸出处#xff1a;极简壁纸_海量电脑桌面壁纸美图_4K超高清_最潮壁纸网站#xff09; 前言 在学习过语法之后若是想要继续对该语言深入学习#xff0c;那就要开始着手数据结构与算法方面的学习啦。在本篇文章中#xff0c;作者将带大家实现C语言…
每日壁纸分享壁纸出处极简壁纸_海量电脑桌面壁纸美图_4K超高清_最潮壁纸网站 前言 在学习过语法之后若是想要继续对该语言深入学习那就要开始着手数据结构与算法方面的学习啦。在本篇文章中作者将带大家实现C语言中最简单的一个数据结构顺序表 目录
前言
顺序表
数据结构的概念
1数据结构简介
2为什么需要数据结构
顺序表的概念
1线性表的概念
2顺序表 顺序表的概念
动态顺序表的实现
1头文件
1 顺序表的结构如下
2增删改查功能如下 头文件源码
2源文件
1初始化、重置
2尾插、判空扩容
1判空扩容函数实现
2尾插函数实现
3头插
4尾删、头删 1判定是否有值 函数实现 2尾删函数实现 3头删函数实现
5指定位置删除
6指定位置插入
7查找打印函数实现
3函数功能测试 SeqList.h文件代码 SeqList.c文件代码 顺序表 在开始顺序表之前按照惯例我先简单介绍一下什么是数据结构与为什么要有这么多数据结构的原因。 数据结构的概念
1数据结构简介 数据结构是指计算机存储、组织数据的方式。数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合。数据结构反映数据的内部构成即数据由那部分构成以什么⽅式构成以及数据元素之间呈现的结构。 数据结构具备两个特点 1可以存储数据 2储存的数据方便查找 2为什么需要数据结构 程序中如果不对数据进⾏管理可能会导致数据丢失、操作数据困难、野指针等情况。通过数据结构能够有效将数据组织和管理在⼀起。按照我们的⽅式任意对数据进⾏增删改查等操作。 其实数组就是一个最简单的数据结构但是为什么有了数组这类的数据结构还要其他的数据结构呢 主要的原因是数组不满足于复杂场景数据的管理弊端如下 1数组仅能存储同类型的数据 2数组可提供的接口不足以支撑复杂场景的数据处理 顺序表的概念 在讲顺序表之前我不得不先提一下线性表因为顺序表就是线性表的一种。如果说线性表是水果那么顺序表就是香蕉。 1线性表的概念 线性表指的是具有相同特性的一类数据结构的统称何为相同特性呢如下
在逻辑结构上一定是线性的在物理结构上不一定是线性的 很简单我们可以将其理解为在逻辑上线性表数据结构是像一条线一样头尾相连环环相扣但是在内存存放上可能是分开存放。 常⻅的线性表有顺序表、链表、栈、队列、字符串.. 2顺序表 那么通过前文我们已经能够理解顺序表是线性表的一种接下来就开始引入正题。 顺序表的概念 顺序表是线性表的一种并且因为顺序表的底层结构是数组所以顺序表在逻辑结构上是线性的在物理结构上也是线性的。 顺序表就是对数组进行封装并实现了常用的增删改查等接口。 而顺序表也分为两种一种是静态顺序表一种是动态顺序表。 1静态顺序表是由定长数组实现的其弊端较为明显内存空间固定给多了容易浪费给少了又不够用。基于以上的原因静态顺序表的适用场景较小故本文主要讲的是动态顺序表的实现。 2动态顺序表即是动态开辟空间可以对空间进行调节避免出现浪费或者空间不够用的情况同时在其动态内存的基础上增加了增删改查等接口实现了对数据初步的管理。 动态顺序表的实现 在正式开始实现之前我需要对本次代码实现的方式进行说明以便读者能够更好地阅读本文。 本次顺序表的实现将采用声明、引用分开的方式如下图 我们可以将头文件设想为一个目录里面记录了我们需要实现的功能这样就可以在实现之前将需要实现的功能先写在头文件中再一一实现这样有助于我们去思考与编写代码。 1头文件 在头文件中除了包含需要的头文件之外剩下的就是函数声明及结构申明了我将以逻辑思维的顺序往后写。 1 顺序表的结构如下 2增删改查功能如下 当我们完成顺序表的基础结构后接下来就要着手考虑需要实现哪些接口先写出声明再依照申明一一实现。 到现在为止顺序表的头文件我们便已经写好了接下来的工作便是在源文件中照猫画虎再根据实际碰见的问题增加其他函数。 头文件源码 此头文件不代表最终的头文件在后续代码中若是新增函数也会在该头文件中声明。
#pragma once#include stdio.h
#include stdlib.h
#include stdbool.h
#include assert.htypedef int SLDataType;typedef struct SeqList
{SLDataType* a;size_t size; //顺序表中有效元素个数size_t capacity;//顺序表当前内存空间大小
}SL;//顺序表初始化
void SLInit(SL* ps);//重置顺序表
void SLReset(SL* ps);//尾插
void SLPushBack(SL* ps, SLDataType x);//头插
void SLpushFront(SL* ps, SLDataType x);//尾删
void SLPopBack(SL* ps);//头删
void SLPopFront(SL* ps);//指定位置删除
void SLErase(SL* ps, int pos);//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);//查找
void SLFind(SL* ps, SLDataType target);//打印
void SLprint(SL* ps); 2源文件 在源文件中我们就是需要将头文件中所声明的函数一一实现。 在这里我将会对每个函数进行深入讲解其原理。 第一步一定要先在 SeqList.c源文件中包含我们刚才写的头文件 1初始化、重置 由于初始化与重置函数较为简单于是我便将这两个函数放在一起进行讲解。 如下 2尾插、判空扩容 尾插顾名思义即是从历史数据的后面开始存放数据不需要做其他操作。 而只要插入数据就涉及到两种情况当前空间足够时和当前空间不足时解决方法如下 既然要扩容那么如何扩容每次扩容多大呢答一般来说每次扩容原空间的1.5倍或者2倍 1判空扩容函数实现
那么现在目标明确我们便加上一个扩容函数如下声明同步到头文件中 2尾插函数实现 在上文中已经实现了判空扩容函数于是我们在尾插函数中便可以直接调用该函数函数实现如下 3头插 头插即是将元素插入到下表为0的位置需要先将历史数据全部向后移一位。 如何移动呢从后向前移 如图当使用头插时需要从后向前依次不会对没有移动的数据进行覆盖向后赋值一位以实现历史数据整体后移。当整体后移后即可将下标为0的位置赋值为x。 代码如下 4尾删、头删 在实现之前需要大家仔细想一下若是顺序表中没有数据时是否可以删除呢 答案是不行所以我们需要增加一个函数来判定函数是否含有数据。 1判定是否有值 函数实现 2尾删函数实现 3头删函数实现 5指定位置删除 在实现之前我还是想请大家思考一个问题指定位置删除那么这个指定位置可以是任意的数字吗 答案是当然不能所以我们还需要对指定位置的变量进行限制。 再者就是指定的位置是按照下标的位置还是按照元素排列的位置呢两者都行但是我们需要在这里指定一个标准我在这是按照元素排列的次序为指定位置实现的。 6指定位置插入 与上文同理以元素排列次序为基准进行指定。 7查找打印 这两个函数实现就较为简单了查找只需要直接遍历所有元素找出指定元素打印函数为常见的遍历打印。 3函数功能测试 实际上我是在实现一个功能后就会立马对其进行调试但是在文章中展示调试过程就显得比较冗长故我将所有函数功能实现完毕之后再对其进行一个总调试以让大家看到其功能实现。 当然测试并不止这些一般需要使用特殊值进行测试我这里仅仅是对其功能进行简单的使用。 SeqList.h
#pragma once#include stdio.h
#include stdlib.h
#include stdbool.h
#include assert.htypedef int SLDataType;typedef struct SeqList
{SLDataType* a;size_t size; //顺序表中有效元素个数size_t capacity;//顺序表当前内存空间大小
}SL;//顺序表初始化
void SLInit(SL* ps);//重置顺序表
void SLReset(SL* ps);//尾插
void SLPushBack(SL* ps, SLDataType x);//头插
void SLpushFront(SL* ps, SLDataType x);//尾删
void SLPopBack(SL* ps);//头删
void SLPopFront(SL* ps);//指定位置删除
void SLErase(SL* ps, int pos);//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);//查找
void SLFind(SL* ps, SLDataType target);//打印
void SLprint(SL* ps);//判空扩容
void SLCheckCapacity(SL* ps);//判定是否有值
bool SLEmpty(SL* ps);SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1 #include SeqList.h//初始化
void SLInit(SL* ps)
{ps-a NULL;ps-capacity ps-size 0;
}//重置
void SLReset(SL* ps)
{assert(ps);free(ps-a);ps-a NULL;ps-capacity ps-size 0;
}void SLCheckCapacity(SL* ps)
{assert(ps);//当有效元素空间大小说明此时空间已经满了需要扩容if (ps-capacity ps-size){//当第一次进入该函数时函数内存容量为零需要我们对其进行赋值我给其赋值4size_t NewCapacity ps-capacity 0 ? 4 : 2 * ps-capacity;ps-capacity NewCapacity;//设置临时指针接收其返回值并对其返回值进行判断若是不为空再赋值SLDataType* tmp (SLDataType*)realloc(ps-a, sizeof(SLDataType) * ps-capacity);if (tmp NULL){perror(realloc);return 1;}ps-a tmp;tmp NULL;}
}//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);ps-a[ps-size] x;
}//头插
void SLpushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);for (int i (ps-size - 1); i 0; i--){ps-a[i 1] ps-a[i];}ps-a[0] x;ps-size;
}//尾删
void SLPopBack(SL* ps)
{assert(ps);assert(!SLEmpty(ps));ps-size--;
}//头删
void SLPopFront(SL* ps)
{assert(ps);assert(!SLEmpty(ps));for (int i 0; i ps-size - 1; i){ps-a[i] ps-a[i 1];}ps-size--;
}//判定是否有值
bool SLEmpty(SL* ps)
{return ps-size 0;
}//指定位置删除
void SLErase(SL* ps, int pos)
{assert(ps);assert(!SLEmpty(ps));assert(pos 0 pos ps-size);for (int i (pos - 1); i ps-size - 1; i){ps-a[i] ps-a[i 1];}ps-size--;
}//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos 0 pos ps-size);SLCheckCapacity(ps);for (int i ps-size - 1; i pos - 1; i--){ps-a[i 1] ps-a[i];}ps-a[pos - 1] x;ps-size;
}//查找
void SLFind(SL* ps, SLDataType target)
{for (int i 0; i ps-size; i){if (ps-a[i] target){printf(找到了\n);return;}}printf(没找到\n);return;
}//打印
void SLprint(SL* ps)
{for (int i 0; i ps-size; i){printf(%d , ps-a[i]);}printf(\n);
}