《数据结构》--顺序表
C语言语法基础到数据结构与算法,前面已经掌握并具备了扎实的C语言基础,为什么要学习数据结构课程?--我们学完本章就可以实践一个:通讯录项目
简单了解过后,通讯录具备增加、删除、修改、查找联系人等操作。要想实现通讯录项目必须有两个技术关键:(1)C语言语法基础(2)数据结构 之 顺序表/链表。
一、初步了解数据结构
什么是数据结构?数据结构就是“数据”与“结构”两个词组合而来。
什么是数据:常见的数值1、2、3......、教务系统里保存的用户信息(姓名、性别、年龄、学历等)、网页里的图片、视频、文字等等,都是数据。(我们知晓的所有信息都可以称之为数据,数据在计算机中存储的方式都是二进制数字,包括图文、视频等)
什么是结构:当我们想要大量使用同一类型的数据时,通过手动定义大量的独立的变量对于程序来说,可读性非常差,我们可以借助数组这样的数据结构将大量的数据组织在一起,结构也可以理解为组织数据的方式。
概念:数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在的一种或多种特定关系的数据元素的集合。数据结构反映数据的内部构成,即数据由哪部分构成、以什么方式构成、以及数据元素之间呈现的结构。
小结:
1.能够存储数据(如顺序表、链表等结构)
2.存储的数据能够方便查找
为什么需要数据结构?通过数据结构可以有效的将数据组织和管理在一起。按照我们的方式任意对数据进行增删查改等操作。最基础的数据结构:数组。
【思考】有了数组,为什么还要学习其它数据结构?
假定数组有10个空间,已经使用了5个,向数组中插入数据的步骤有:
1.求数组的长度(求总长是为了判断有效个数与最大长度是否相等,数组满员还能继续插入吗?) 2.求数组的有效数据个数 3.向下标为数据有效个数的位置插入数据
假设数据量非常的庞大,频繁的获取数组有效个数会影响程序执行效率。
结论:最基础的数据结构能提供的操作已经不能完全满足复杂算法的实现。
二、顺序表
1.顺序表的概念及结构
顺序表是一种线性表。线性表(linear list)是n个相同特性的数据元素的有限序列。线性表是一种在实际中广泛应用的数据结构,常见的线性表包括:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上的存储方式通常是顺序(数组)存储和链式存储。
如何理解逻辑结构和物理结构?下面给大家画一张图:
第一种就是物理顺序和逻辑顺序一致,在一段连续的空间中依次存放数据。第二种就是这些数据逻辑上是一条线,但由于存储的位置不连续,在忽略其它空间的情况下,将这些空间取出并将其放置到一条直线上就可以验证它的线性存储形式是逻辑线性,物理上的存储是不确定的。
2.顺序表分类
顺序表和数组的区别:顺序表的底层结构是数组,对数组的封装,实现了常用的增删查改等接口。
分类:静态顺序表-动态顺序表
//静态顺序表
typedef int DataType;
#define SQLIST_INIT_LENGTH 10
typedef struct SqList{DataType arr[SQLIST_INIT_LENGTH];size_t _size;//有效数据个数,每插入一个数据就会+1,用来记录
}SL;
//静态顺序表缺陷:空间给少了不够用,给多了造成空间浪费
//动态顺序表--按需分配
typedef struct SqList{DataType* arr;size_t _size;//有效数据个数size_t _capacity;//空间容量
}SL;
3.动态顺序表的基本操作
#define LIST_INIT_SIZE 10
typedef int DataType;
typedef struct SqList{DataType* arr;size_t size;//有效数据个数size_t capacity;//空间容量
}SL;//判空、取长、寻值
bool isEmpty(SL s);
int GetSize(SL s);
int SLFind(SL s,DataType data);//初始化与销毁
void SLInit(SL* s);
void SLDestroy(SL* s);
//打印
void SLPrint(SL s);
//扩容
void SLCheckCapacity(SL* s);
//修改指定位置的值
void UpdateNode(SL* s,int index,DataType data);//指定位置之前插入/删除数据
void SLInsert(SL* s,int index,DataType data);
void DeleteByIndex(SL* s,int index);
//按值删除数据
void DeleteByData(SL& s,DataType data);//增删操作也可以有下面的几种
//头插、头删、尾插、尾删
void SLInsert_Head(SL* s,DataType data);
void SLDelete_Head(SL* s);
void SLInsert_Tail(SL* s,DataType data);
void SLDelete_Tail(SL* s);
三、动态顺序表的实现
1.顺序表的判空操作
顺序表的内容是否为空主要就是看里面的动态数组是否指向空指针。然后返回这个表达式的结果(布尔类型)。
bool isEmpty(SL s)
{return (s.arr == nullptr);
}
2.顺序表的长度
我们说的顺序表的长度是有效数据个数而非顺序表的空间总量 。所以我们返回的就是顺序表内部的size属性。
int GetSize(SL s)
{return s.size;
}
3.查找某值在顺序表的位置
查找某值在顺序表的位置时,首先判断顺序表是不是空的,如果是空的,那就没必要再继续了,直接返回-1。否则,循环遍历直至顺序表中顺组的有效长度的最后一个值。如果循环结束仍未找到,返回-1。那么综上返回-1就代表表内无该元素。
int SLFind(SL s, DataType data)
{if (isEmpty(s))return -1;else{for (int i = 0; i < s->size; i++) {if (*(s->arr + i) == data) {return i;}}}return -1;
}
4.顺序表的初始化与销毁
初始化时使用宏定义的初始化长度LIST_INIT_SIZE,使用malloc为数组申请一定长度的空间,然后对该表进行判断,如果仍然为空说明malloc申请空间时由于某些原因申请失败了,离开程序。否则就将顺序表的最大长度设为初始值,有效长度设为0。
销毁顺序表时,将顺序表长度和空间容量都置零,令数组指针指向NULL(按理来说nullptr更为严谨)。最后使用free释放内存空间。
//初始化顺序表:给arr开辟10个空间void SLInit(SL* s){s->arr = (DataType*)malloc(sizeof(DataType) * LIST_INIT_SIZE);if (isEmpty(*s))exit(OVERFLOW);//s->arr = new DataType[LIST_INIT_SIZE];s->capacity = LIST_INIT_SIZE;s->size = 0;//尚未存储数据}//销毁顺序表void SLDestroy(SL* s){assert(s->arr);//在头文件<assert.h>中s->capacity = s->size = 0;s->arr = NULL;free(s->arr);cout << "销毁完毕" << endl;}
5.顺序表打印
如果顺序表为空,那还打印什么,直接告诉用户顺序表为空就可以了。非空的话,那就循环遍历顺序表的有效数据,将其中存储的值依次打印出来。
void PrintSqlist(SL s)
{if (isEmpty(s))cout << "顺序表为空";else {for (int i = 0; i < s.size; i++)cout << *(s.arr + i) << " ";}cout << endl;
}
6.顺序表插入数据
此处涉及到一个扩容的问题:当有效长度与最大容量相等时,说明顺序表满了,需要使用realloc动态扩容,考虑到不断扩容会导致效率变低或者出现问题,我们每次表满时直接选择二倍扩容。
//尾插
void SLInsert_Tail(SL* s, DataType data)
{if (isEmpty(*s)) {SLInit(s);//如果顺序表为空,则开辟一个顺序表}if ((s->size) == (s->capacity)){//2倍扩容DataType* tmp = (DataType*)realloc(s->arr, (s->capacity * 2) * sizeof(DataType));assert(tmp);//判断指针是否为空s->arr = tmp;//(s->capacity) *= 2;}*(s->arr + s->size) = data;(s->size)++;
}//指定位置插入
void SLInsert(SL* s, int index, DataType data)
{if (isEmpty(*s)) SLInit(s);if (index < 0 || index > s->size) return;if (s->size == s->capacity){int newcapacity = s->capacity * 2;DataType* tmp = (DataType*)realloc(s->arr, sizeof(DataType) * newcapacity);assert(tmp);s->arr = tmp;}for (int i = s->size; i >= index; i--){s->arr[i + 1] = s->arr[i];}s->arr[index] = data;s->size++;
}
7.顺序表删除数据
//删除顺序表第index位数据(按位删)
void DeleteByIndex(SL* s, int index)
{if (isEmpty(*s)|| index > s->size||index < 0)cout << "空表或索引溢出" << endl;else {for (int i = index; i < (s->size); i++) {DataType tmp = *(s->arr + i);*(s->arr + i) = *(s->arr + i + 1);*(s->arr + i + 1) = tmp;}(s->size)--;}cout << "删除成功" << endl;
}//删除顺序表数据data(按值删)
void DeleteByData(SL& s, DataType data)
{if (isEmpty(s))cout << "空表" << endl;else {for (int i = 0; i < s.size; i++){if (*(s.arr + i) == data) {for (int j = i; j < s.size; j++){DataType tmp = *(s.arr + j);*(s.arr + j) = *(s.arr + j + 1);*(s.arr + j + 1) = tmp;}s.size--; }cout << "删除完毕" << endl;}}
}
8.修改顺序表内容
void UpdateNode(SL* s, int index, DataType data)
{if (isEmpty(*s))cout << "顺序表为空" << endl;else{*(s->arr + index) = data;cout << "修改成功" << endl;}
}
9.顺序表扩容
扩容操作参考插入时的特殊处理。
我们在下节的项目实战中完成顺序表实现通讯录。(大家先试着完成写一写自己的通讯录系统,独立的完成每一个小项目才能为完成大项目积累经验)。加油各位!
相关文章:

《数据结构》--顺序表
C语言语法基础到数据结构与算法,前面已经掌握并具备了扎实的C语言基础,为什么要学习数据结构课程?--我们学完本章就可以实践一个:通讯录项目 简单了解过后,通讯录具备增加、删除、修改、查找联系人等操作。要想实现通…...

Qt:愚蠢的qmake
博主参与了一个使用qmake构建的项目,包含几百个源文件,最近遇到一个恼人的问题:有时仅仅修改了一个.cpp文件,构建项目时就有可能触发全编译。但是编译时又会命中ccache的缓存,这说明源代码实际上内容并没有发生变化。即…...

Apache Dubbo:分布式服务框架的深度解析
文章目录 引言官网链接Dubbo 原理架构概览通信协议负载均衡 基础使用1. 引入依赖2. 配置服务提供者3. 配置服务消费者4. 配置注册中心 高级使用1. 集群容错2. 泛化引用3. 异步调用 优缺点优点缺点 结论 引言 Apache Dubbo 是一个高性能、轻量级的开源 Java RPC 框架。它提供了…...

【前端学习】CSS三大特性
CSS三大特性 CSS的三大特性是为了化简代码、定位问题并且解决问题 继承性 继承性特点: 子级默认继承父级的文字控制属性。注意:如果标签自己有样式则生效自己的样式,不继承。 <!DOCTYPE html> <html lang"en"><…...

了解网络是如何运作
“Web 的工作原理”提供了一个简化的视图,用于了解在计算机或手机上的 Web 浏览器中查看网页时发生的情况。 这个理论对于短期内编写 Web 代码来说并不是必需的,但不久之后,你就会真正开始从理解后台发生的事情中受益。 客户端和服务器 连接到 Internet 的计算机称为客户端和…...

传输层协议——TCP
TCP协议 TCP全称为“传输控制协议”,要对数据的传输进行一个详细的控制。 特点 面向连接的可靠性字节流 TCP的协议段格式 源/目的端口:表示数据从哪个进程来,到哪个进程4位首部长度:表示该TCP头部有多少字节(注意它…...

C++相关概念和易错语法(23)(set、仿函数的应用、pair、multiset)
1.set和map存在的意义 (1)set和map的底层都是二叉搜索树,可以达到快速排序(当我们按照迭代器的顺序来遍历set和map,其实是按照中序来遍历的,是排过序的)、去重、搜索的目的。 (2&a…...

netty入门-3 EventLoop和EventLoopGroup,简单的服务器实现
文章目录 EventLoop和EventLoopGroup服务器与客户端基本使用增加非NIO工人NioEventLoop 处理普通任务与定时任务 结语 EventLoop和EventLoopGroup 二者大概是什么这里不再赘述,前一篇已简述过。 不理解也没关系。 下面会简单使用,看了就能明白是什么 这…...

通信原理-思科实验五:家庭终端以太网接入Internet实验
实验五 家庭终端以太网接入Internet实验 一实验内容 二实验目的 三实验原理 四实验步骤 1.按照上图选择对应的设备,并连接起来 为路由器R0两个端口配置IP 为路由器R1端口配置IP 为路由器设备增加RIP,配置接入互联网的IP的动态路由项 5.为路由器R1配置静…...

【Vue】vue概述
1、简介 Vue.js(简称Vue)是一款用于构建用户界面的渐进式JavaScript框架。由前Google高级软件工程师尤雨溪(Evan You)于2014年创建,是一个独立且社区驱动的开源项目。Vue.js基于标准的HTML、CSS和JavaScriptÿ…...

Docker use experience
#docker command docker load -i <镜像文件.tar> docker run -it -d --name 容器名 -p 宿主机端口:容器端口 -v 宿主机文件存储位置:容器内文位置 镜像名:Tag /bin/bash docker commit -m"提交的描述信息" -a"作者" 容器ID 要…...

Android平台RTSP|RTMP直播播放器技术接入说明
技术背景 大牛直播SDK自2015年发布RTSP、RTMP直播播放模块,迭代从未停止,SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述,全自研内核,行业内一致认可的跨平台RTSP、RTMP直播播放器。本文以Android平台…...

数据结构——栈(顺序结构)
一、栈的定义 栈是一种数据结构,它是一种只能在一端进行插入和删除操作的特殊线性表。这一端被称为栈顶,另一端被称为栈底。栈按照后进先出(LIFO)的原则进行操作(类似与手枪装弹后射出子弹的顺序)。在计算…...

速盾:cdn能防御ddos吗?
CDN(内容分发网络)是一种广泛应用于互联网中的技术,它通过将内容分发到全球各地的服务器上,以提高用户在访问网站时的加载速度和稳定性。然而,CDN是否能够有效防御DDoS(分布式拒绝服务)攻击是一…...

分享 2 个 .NET EF 6 只更新某些字段的方法
前言 EF 更新数据时,通常情况下,是更新全部字段的,但实际业务中,更新全部字段的情况其实很少,一般都是修改其中某些字段,所以为了实现这个目标,很多程序员通常会这样作: 先从数据库…...

vs code解决报错 (c/c++的配置环境 远端机器为Linux ubuntu)
参考链接:https://blog.csdn.net/fightfightfight/article/details/82857397 https://blog.csdn.net/m0_38055352/article/details/105375367 可以按照步骤确定那一步不对,如果一个可以就不用往下看了 目录 一、检查一下文件扩展名 二、安装扩展包并…...

08 字符串和字节串
使用单引号、双引号、三单引号、三双引号作为定界符(delimiter)来表示字符串,并且不同的定界符之间可以相互嵌套。 很多内置函数和标准库对象也都支持对字符串的操作。 x hello world y Python is a great language z Tom said, "Le…...

vue使用mavonEditor(流程图、时序图、甘特图实现)
mavonEditor 安装mavonEditor $ npm install mavon-editor --save使用 // 全局注册import Vue from vueimport mavonEditor from mavon-editorimport mavon-editor/dist/css/index.css// useVue.use(mavonEditor)new Vue({el: #main,data() {return { value: }}})//局部使用…...

Java实现短信验证码服务
1.首先这里使用的是阿里云的短信服务。 package com.wzy.util;; import cn.hutool.captcha.generator.RandomGenerator; import com.aliyun.dysmsapi20170525.Client; import com.wzy.entity.Ali; import org.springframework.stereotype.Component;/*** Author: 顾安* Descri…...

python中的线程
线程 线程概念 线程 在一个进程的内部, 要同时干多件事, 就需要同时运行多个"子任务", 我们把进程内的这些"子任务"叫做线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中, 是进程的实际运作单位。一条线程指的是进程中一个单一顺序的控制流…...

hcip学习 多实例生成树,VRRP工作原理
一、STP 和 RSTP 解决了什么问题 1、STP:解决了在冗余的二层网络中所出现的环路问题 2、RSTP:在 STP 的基础上,解决了 STP 收敛速度慢的问题,引入了一些 STP 保护机制,使其网络更加稳定 二、MSTP 针对 RSTP 的改进 …...

Docker搭建群晖
Docker搭建群晖 本博客介绍在docker下搭建群晖 1.编辑docker-compose.yml文件 version: "3" services:dsm:container_name: dsmimage: vdsm/virtual-dsm:latestenvironment:DISK_SIZE: "16G"cap_add:- NET_ADMIN ports:- 8080:50…...

【java】BIO,NIO,多路IO复用,AIO
在Java中,处理I/O操作的模型主要有四种:阻塞I/O (BIO), 非阻塞I/O (NIO), 异步I/O (AIO), 以及IO多路复用。下面详细介绍这四种I/O模型的工作原理和应用场景。 1. 阻塞I/O (BIO) 工作原理 阻塞I/O是最传统的I/O模型。在这种模型中,当一个线…...

服务器怎样减少带宽消耗的问题?
择业在使用服务器的过程中会消耗大量的带宽资源,而减少服务器的带宽消耗则可以帮助企业降低经济成本,同时还能够提高用户的访问速度,那么服务器怎样能减少带宽的消耗呢?本文就来带领大家一起来探讨一下吧! 企业可以选择…...

linux 报错:bash: /etc/profile: 行 32: 语法错误:未预期的文件结束符
目录 注意错误不一定错在最后一行 i进入编辑 esc退出编辑 :wq 保存编辑退出 :q!不保存退出 if [ $# -eq 3 ] then if [ ! -e "$1" ]; then miss1 $1 elif [ ! -e "$2" -a ! -e "$3" ]; then miss2and3…...

MySQL练习(5)
作业要求: 实现过程: 一、触发器 (1)建立两个表:goods(商品表)、orders(订单表) (2)在商品表中导入商品记录 (3)建立触发…...

泛型新理解
1.创建三个类,并写好对应关系 package com.jmj.gulimall.study;public class People { }package com.jmj.gulimall.study;public class Student extends People{ }package com.jmj.gulimall.study;public class Teacher extends People{ }2.解释一下这三个方法 pub…...

JavaSE--基础语法--继承和多态(第三期)
一.继承 1.1我们为什么需要继承? 首先,Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是 现实世界错综复杂,事物之间可能会存在一些关联,那在设计程…...

高级java每日一道面试题-2024年7月23日-什么时候用包装类, 什么时候用原始类
面试官: 你在什么时候用包装类, 什么时候用原始类? 我回答: 在Java开发中,理解何时使用包装类(Wrapper Classes)和何时使用原始类(Primitive Types)是非常重要的。这主要取决于你的具体需求以及Java语言本身的一些限…...

LINUX之MMC子系统分析
目录 1. 概念1.1 MMC卡1.2 SD卡1.3 SDIO 2. 总线协议2.1 协议2.2 一般协议2.3 写数据2.4 读数据2.5 卡模式2.5.1 SD卡模式2.5.2 eMMC模式 2.6 命令2.6.1 命令类2.6.2 详细命令 2.7 应答2.8 寄存器2.8.1 OCR2.8.2 CID2.8.3 CSD2.8.4 RCA2.8.5 扩展CSD 3. 关键结构3.1 struct sdh…...