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

数据结构-Data Structure (顺序表专题)

标题

数据结构

概念

数据结构是计算机存储、组织数据的方式。它是指相互之间存在⼀种或多种特定关系的数据元素的集合。分为线性结构和非线性结构。

程序中如果不对数据进⾏管理,可能会导致数据丢失、操作数据困难、野指针等情况。
通过数据结构,能够有效将数据组织和管理在⼀起。按照自己的方式可以任意对数据进行增删改查等操作。

线性结构

概念

线性结构是数据元素之间存在一对一线性关系的数据结构,所有元素按前后次序排成一条连续的 “线性序列”。

线性结构在物理结构不一定是连续的,但在逻辑结构上一定是连续的。

常见类型

顺序表列表队列字符串,,,

顺序表

概念

顺序表是采用一段连续的内存空间依次存储数据元素的线性结构,基于数组实现,元素的逻辑顺序与物理存储顺序完全一致。

分类
静态顺序表

概念:使用定长数组存储元素。

#define N 100 typedef struct Seqlist { int arr[N]; //定长数组 int size; //定义有效数据的个数 }SL;
动态顺序表
typedef struct Seqlist { int* arr; //定长数组 int size; //定义有效数据的个数 int capacity; //定义可变空间大小 }SL;
动态顺序表的实现
创建
//定义顺序表的结构 typedef int SLtype; //定义宏 顺序表类型 //定义动态顺序表 typedef struct Seqlist { SLtype* arr; SLtype size; SLtype capacity; }SL;
初始化
//初始化 void SLinit(SL* ps); //定义指针变量来接受地址传参进行初始化 void SLinit(SL* ps) { ps->arr = NULL; ps->size = ps->capacity = 0; }
打印
//打印 void SLprint(SL s); void SLprint(SL s) { for ( int i = 0; i <s.size; i++) { printf("%d ", s.arr[i]); } printf("\n"); }
插入
//插入 void SLpushback(SL* ps, SLtype x); //尾部插入 void SLpushfront(SL* ps, SLtype x); //头部插入 void checkcapacity(SL* ps) { if (ps->capacity == ps->size) //如果相等,需要申请空间 { //malloc calloc relloc-> 涉及增容 //三目表达式 //将初始化的capacity空间大小设值,若为0,初始化为4,若不为0,设值为两倍增容 int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity; //增容一般使用倍数增容方式,这里使用最常见的两倍增容。 SLtype* tmp = (SLtype*)realloc(ps->arr, newcapacity * 2 * sizeof(SLtype)); if (tmp == NULL) { perror("realloc fail!"); exit(1); } ps->arr = tmp; ps->capacity = newcapacity; } } void SLpushback(SL* ps, SLtype x) { /*ps->arr[ps->size] = x; ++ps->size;*/ /*if (ps ==NULL) { return; }*/ assert(ps); //判断空间大小是否足够 checkcapacity(ps); ps->arr[ps->size++] = x; } void SLpushfront(SL* ps, SLtype x) { assert(ps); checkcapacity(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); //尾部删除 void SLpopfront(SL* ps); //头部删除 void SLpopback(SL* ps) { assert(ps); //判断顺序表是否为空 assert(ps->size); //ps->arr[ps->size - 1] = -1; --ps->size; } void SLpopfront(SL* ps) { assert(ps); assert(ps->size); for ( int i = 0; i < ps->size-1; i++) { ps->arr[i] = ps->arr[i + 1]; } ps->size--; }
销毁
//销毁 void SLdestroy(SL* ps); void SLdestroy(SL* ps) { if (ps->arr) { free(ps->arr); } ps->arr = NULL; ps->size = ps->capacity = 0; }
指定位置插入
//指定位置插入 void SLInsert(SL* ps, int pos, SLType x); void SLInsert(SL* ps, int pos, SLType x) { assert(ps); 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[pos] = x; ps->size++; }
指定位置删除
//指定位置删除 void SLErase(SL* ps, int pos); void SLErase(SL* ps, int pos) { assert(ps); assert(pos >= 0 && pos <= ps->size); for (int i = pos; i <ps->size-1; i++) { ps->arr[i] = ps->arr[i + 1]; } ps->size--; }
查找
//查找 int SLFind(SL* ps, SLType x); int SLFind(SL* ps, SLType x) { assert(ps); for ( int i = 0; i < ps->size; i++) { if (ps->arr[i] == x) { return i; } } return -1; } //测试 int find = SLFind(&s1,3); if (find <0) { printf("no found!"); } else { printf("find it! The subscript is %d", find); }

完整代码如下:

1. 顺序表头文件 seqlist.h 定义

#pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> //顺序表 //创建 typedef int SLType; //指定类型 typedef struct seqlist { SLType* arr; int size; int capacity; }SL; //指定顺序表名称为SL //初始化 void SLInit(SL* ps); //打印 void SLPrint(SL s); //销毁 void SLDestroy(SL* ps); //头插 void SLPushFront(SL* ps,SLType x); //尾插 void SLPushBack(SL* ps, SLType x); //头删 void SLPopFront(SL* ps); //尾删 void SLPopBack(SL* ps); //指定位置插入 void SLInsert(SL* ps, int pos, SLType x); //指定位置删除 void SLErase(SL* ps, int pos); //查找 int SLFind(SL* ps, SLType x);

2.执行源文件seqlist.c

#define _CRT_SECURE_NO_WARNINGS 1 #include "seqlist.h" //初始化 void SLInit(SL* ps) { ps->arr = NULL; ps->capacity = ps->size = 0; } //打印 void SLPrint(SL s) { for (int i = 0; i < s.size; i++) { printf("%d ", s.arr[i]); } printf("\n"); } //销毁 void SLDestroy(SL* ps) { if (ps->arr) { free(ps->arr); } ps->size = ps->capacity = 0; } //申请空间 void SLCheckCapacity(SL* ps) { if (ps->size==ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity; SLType* tmp = (SLType*)realloc(ps->arr, newcapacity*sizeof(SLType)); if (tmp == NULL) { perror("realloc fail!"); } ps->arr = tmp; ps->capacity = newcapacity; } } //头插 void SLPushFront(SL* ps, SLType 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 SLPushBack(SL* ps, SLType x) { assert(ps); SLCheckCapacity(ps); ps->arr[ps->size++] = x; } //头删 void SLPopFront(SL* ps) { assert(ps); assert(ps->size); for (int i = 0; i < ps->size-1; i++) { ps->arr[i] = ps->arr[i + 1]; } ps->size--; } //尾删 void SLPopBack(SL* ps) { assert(ps); assert(ps->size); --ps->size; } //指定位置插入 void SLInsert(SL* ps, int pos, SLType x) { assert(ps); 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[pos] = x; ps->size++; } //指定位置删除 void SLErase(SL* ps, int pos) { assert(ps); assert(pos >= 0 && pos <= ps->size); for (int i = pos; i <ps->size-1; i++) { ps->arr[i] = ps->arr[i + 1]; } ps->size--; } //查找 int SLFind(SL* ps, SLType x) { assert(ps); for ( int i = 0; i < ps->size; i++) { if (ps->arr[i] == x) { return i; } } return -1; }

3.测试文件test.c

#define _CRT_SECURE_NO_WARNINGS 1 #include "seqlist.h" void test01() { SL s1; SLInit(&s1); SLPushBack(&s1, 1); SLPushBack(&s1, 2); SLPrint(s1); SLPushFront(&s1, 3); SLPushFront(&s1, 4); SLPrint(s1); SLPopBack(&s1); SLPrint(s1); SLPopFront(&s1); SLPrint(s1); SLInsert(&s1, 0, 6); SLPrint(s1); SLInsert(&s1,s1.size, 9); SLPrint(s1); SLInsert(&s1, 1, 7); SLPrint(s1); SLErase(&s1, 3); SLPrint(s1); SLErase(&s1, s1.size); SLPrint(s1); SLErase(&s1, 0); SLPrint(s1); int find = SLFind(&s1,3); if (find <0) { printf("no found!"); } else { printf("find it! The subscript is %d", find); } } int main() { test01(); return 0; }

代码运行结果如下图所示:

通讯录项目

数据结构设计

  • 定义通讯录中联系人的结构体(如姓名、电话、地址等字段)
  • 顺序表的存储结构及容量管理策略(静态数组或动态扩容)

核心功能实现

  • 初始化通讯录:分配内存或设置初始容量
  • 添加联系人:检查容量并插入数据
  • 删除联系人:查找并移除数据,处理后续元素移位
  • 查找联系人:按姓名或关键字遍历搜索
  • 修改联系人信息:定位后更新字段
  • 显示所有联系人:遍历输出

代码实现

定义通讯录结构体 c.h
#pragma once //定义通讯录联系人结构体 //姓名 性别 年龄 电话 地址 #define NM 20 #define GM 10 #define AM #define TM 20 #define ADM 100 typedef struct PersonInfo { char name[NM]; char gender[GM]; int age; char tel[TM]; char addr[ADM]; }Peo;
在顺序表头文件当中指定类型 s.h
typedef Peo SLType; //指定类型
对通讯录进行操作 c.h
//对通讯录进行操作 // //前置声明 typedef struct seqlist contact; //初始化 void ContactInit(contact* con); //销毁 void ContactDestroy(contact* con); //插入数据 void ContactInsert(contact* con); //删除数据 void ContactErase(contact* con); //修改数据 void ContactModify(contact* con); //查找数据 void ContactFind(contact* con); //打印显示 void ContactShow(contact* con);
通讯录初始化 .c
void ContactInit(contact* con) { SLInit(con); //直接调用即可 }
添加数据
void ContactAdd(contact* con) { //获取用户输入信息 姓名 性别 年龄 电话 住址 Peo info; printf("please input name:\n"); scanf("%s", info.name); printf("please input gender:\n"); scanf("%s", info.gender); printf("please input age:\n"); scanf("%d", &info.age); printf("please input telephone:\n"); scanf("%s", info.tel); printf("please input address:\n"); scanf("%s", info.addr); //添加数据 SLPushBack(con, info); }
删除数据
int FindName(contact* con,char name[]) { for (int i = 0; i < con->size; i++) { if (0 == strcmp(con->arr[i].name,name)) //找到 { return i; } } return -1; //没有找到 } void ContactErase(contact* con) { char name[NM]; printf("please input name that need delete:\n"); scanf("%s", name); //利用查找方式判断数据是否存在 int find = FindName(con, name); if (find <0) { printf("not found!\n"); return; } SLErase(con, find); //根据返回下标执行删除 printf("delete done!\n"); }
修改数据
void ContactModify(contact* con) { char name[NM]; printf("please input name that need modify:\n"); scanf("%s", name); int find = FindName(con, name); if (find <0) { printf("not found!\n"); return; } printf("please input new name:\n"); scanf("%s", con->arr[find].name); printf("please input new gender:\n"); scanf("%s", con->arr[find].gender); printf("please input new age:\n"); scanf("%d", con->arr[find].age); printf("please input new telephone:\n"); scanf("%s", con->arr[find].tel); printf("please input new address:\n"); scanf("%s", con->arr[find].addr); }
查找数据
void ContactFind(contact* con) { char name[NM]; printf("please input name that need find\n"); scanf("%s", name); int find = FindName(con, name); if (find <0) { printf("not found!\n"); return; } //表头打印 printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址"); printf("%s %s %d %s %s\n", con->arr[find].name, con->arr[find].gender, con->arr[find].age, con->arr[find].tel, con->arr[find].addr ); }
展示数据
void ContactShow(contact* con) { printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址"); for (int i = 0; i < con->size; i++) { printf("%s %s %d %s %s\n", con->arr[i].name, con->arr[i].gender, con->arr[i].age, con->arr[i].tel, con->arr[i].addr ); } }
通讯录销毁
void ContactDestroy(contact* con) { SLDestroy(con); }
建立通讯录菜单
void menu() { printf("*******************通讯录******************\n"); printf("********1.添加联系人 2.删除联系人*********\n"); printf("********3.修改联系人 4.查找联系人*********\n"); printf("********5.展示联系人 0.退出系统 *********\n"); printf("*******************************************\n"); }
部分效果展示

主函数执行代码如下
int main() { int op = -1; contact con; ContactInit(&con); do{ menu(); printf("please choose a option!\n"); scanf("%d", &op); switch (op) { case 1: ContactAdd(&con); break; case 2: ContactErase(&con); break; case 3: ContactModify(&con); break; case 4: ContactFind(&con); break; case 5: ContactShow(&con); break; case 0: printf("exit!\n"); break; default: break; } } while (op !=0 ); ContactDestroy(&con); return 0; }
http://www.jsqmd.com/news/1399035/

相关文章:

  • 从零构建AI智能体:一份适合新手速通的实战通关地图
  • Snipe-IT Docker部署实战:5步搭建免费IT资产管理系统,附持久化与备份方案
  • 探索未来,领创中等专业学校招生热线全面开放 - 官方资讯
  • 2026年国内工作服定制生产厂家推荐:广东牧马人领衔三大实力派企业 - 变量人生001
  • 中国象棋AI连线工具终极上手指南:3步让Vin象棋替你盯盘、算棋、落子
  • 避开中介引流店铺,认准线下实景门店,武汉黄金回收参考 - 资讯早知道
  • 《ArrayList的初始化和扩容源代码解读》
  • ExPose:革命性单目3D人体姿态估计技术,一键实现精准的身体形状与表情捕捉
  • 告别 30 天倒计时:KMS_VL_ALL_AIO 让 Windows 与 Office 激活一步到位
  • 免费开源的Windows时间统计工具Tai:三步装好,一周后你就再也不会问“时间去哪了“
  • 找不到PS3游戏更新补丁?这份开源下载器上手手册帮你一次搞定
  • 2026年韩国进口食品批发商推荐:行业**引领新趋势 - 官方资讯
  • scrcpy 连接总翻车?新手绕开这 6 类坑,安卓投屏一次就成
  • 揭秘邯郸市领创中等专业学校招生热线,家长学生必看! - 官方资讯
  • 2026马年新春创意线上投票活动方案推荐[最新合集]
  • 掌握OCaml异步编程:Jane Street Workshop中的Async库应用教程
  • 湖北 6‑18 岁全封闭文武学校|** 名单曝光,黄龙文武学校课程、报名须知完整解读 - 全国文武学校招生
  • Tiled地图编辑器核心技术拆解:从位运算图元到插件生态的工程实践
  • Swift分布式系统进阶:集群单例模式(Cluster Singleton)最佳实践
  • gh_mirrors/tr/trading监控与可观测性:Grafana实时追踪JVM性能与业务指标
  • 长三角贵金属回收市场规范化|常州黄金回收行业准则解读,参照苏沪杭监管要求,帮你避开交易风险点 - 日常前沿快讯
  • 佛山处置闲置奢品包小常识 合扬老品牌透明回收大牌包包 - 一刻涨新知
  • 2026广东服务好的智能装备外观设计工作室 机械设备外观设计优质推荐 - 变量人生001
  • 直播抢码总是慢半拍?试试 MHY_Scanner 这个毫秒级扫码登录工具
  • 2026年韩国进口食品批发商推荐**,选对商家很重要! - 官方资讯
  • 探索未来教育之路:邯郸市领创中专招生信息全解析 - 官方资讯
  • Tiled地图编辑器深度解析:分层数据模型与智能地形引擎的实现之道
  • 武汉钻石回收:别只看 4C 证书!这些隐性折价点才是砍价关键 - 奢侈品回收研习社
  • soildworks2025下载分享(只供学习交流)
  • 告别复制粘贴:用 feishu2md 三步搞定飞书文档转 Markdown