C语言:顺序表的实现和通迅录项目实现

news2024/11/15 21:08:13

顺序表

1、顺序表的概念及结构

1.1 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。

2、顺序表分类

• 顺序表和数组的区别
◦ 顺序表的底层结构是数组,对数组的封装实现了常⽤的增删改查等接⼝
• 顺序表分类

2.1◦ 静态顺序表

概念:使⽤定⻓数组存储元素
e0eb1881ab98446fb785c4215be81546.png
静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费

2.2 动态顺序表

不使用定长数组,定义数组的地址。

67450bf375f94a249f5a5c328914fbe2.png
增容一般是以原来空间的两倍到三倍来增容。

3、动态顺序表的实现

3.1初始化和销毁

初始化:

只需要顺序表的数组地址置为空,然后让有效数据个数和空间容量初始化为零即可。

顺序标的销毁:

则是将顺序表内数组的空间释放掉(销毁之前要判空),同时,要指向该数组的指针指为空防止其成为野指针。后让有效数据个数和空间容量指为零即可。

void SLInit(SL* ps)
{
    ps->arr = NULL;
    ps->size = ps->capacity = 0;
}

void SLDestroy(SL* ps)
{
    assert(ps->arr != NULL);
    free(ps->arr);
    ps->arr = NULL;
    ps->size = ps->capacity = 0;
}

3.2动态顺序表 -- 按需申请(扩容)

因为初始化时没有对顺序表申请空间,所以,要先判断空间是否等于零,如果是零的话,就给它赋一个初值,如果不为零的话,那就让它变为原来的两倍。

注意:申请来的空间,不能直接传给顺序表,因为空间有可能申请失败,如果这时直接给的话,就会导致数据丢失。

void SLCheckCapacity(SL* ps)
{
    if (ps->capacity == ps->size)
    {
        int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
        SLdataType* tmp = (SLdataType*)realloc(ps->arr, newCapacity * sizeof(SLdataType));
        assert(tmp != NULL);
        ps->arr = tmp;
        ps->capacity = newCapacity;
    }
}

3.3尾部插⼊删除

尾插:

插入之前要先判断传过要顺序表地址是否为空,和空间够不够,空间不够就要申请(这里调用可上面写的SLCeckCapacity(SL* ps)即可)然后直接插入到最后一个元素的位置即可。

尾删:

删要先判断顺序地址是否为空,顺序表里面元素个数不为零。尾删只需要把有效数据个数减一就行。

void SLPushBack(SL* ps, SLdataType x)
{
    assert(ps!= NULL);
        SLCheckCapacity(ps);
    ps->arr[ps->size] = x;
    ps->size++;
}

void SLPopBack(SL* ps)
{
    assert(ps!= NULL);
    assert(ps->size > 0);
    ps->size--;
}

3.4头部插⼊删除

头插:

头删同样需要判空跟判空间够不够。

因为顺序表里面的元素在物理上是相邻,所以我们在插入第一个元素的时候,要把后面的元素全部往后移,然后再把元素插入空出来的第一个位置里面。

头删:

是把后面的元素全部往前挪一个位置,把第一个元素覆盖掉,再把有效数据减1就行了

void SLPushFront(SL* ps, SLdataType x)
{
	assert(ps != NULL);
		SLCheckCapacity(ps);
	for (int i = ps->size;i>0;i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

void SLPopFront(SL* ps)
{
	assert(ps != NULL);
	assert(ps->size > 0);
	for (int i = 0;i<ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

3.5指定位置之前插⼊/删除数据

插入:

插入之前先看空间够不够和顺序表是否为空

然后只需要将指定位置及其之后的全部元素往后挪一位,再把元素插入到这个指定位置即可。

删:

删之前先判有无元素跟顺序表表是否为空。然后将指定位置之后的数据往前挪动1个元素位置,把要删除的元素覆盖,再将有效元素个数减一即可。

void SLInsert(SL* ps, int pos, SLdataType x)
{
	assert(ps != NULL);
	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 != NULL);
	assert(pos >= 0 && pos < ps->size);
	for (int i =pos;i<ps->size-1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

4.顺序表的应⽤-- 基于动态顺序表实现通讯录

C语⾔基础要求:结构体、动态内存管理、顺序表、⽂件操作
1、功能要求
1)⾄少能够存储100个⼈的通讯信息
2)能够保存⽤⼾信息:名字、性别、年龄、电话、地址等
3)增加联系⼈信息
4)删除指定联系⼈
5)查找制定联系⼈
6)修改指定联系⼈
7)显⽰联系⼈信息

4.1.文件的布置和通讯录结构

上面我们实现的顺序表代码定义放在SeqList.c
声明放在SeqList.h。同时又新建两个文件,一个是Contact.h通讯录实现函数的声明,另一个Contact.c放通讯录函数的实现,再创建一个主函数文件test.c
7ca4dfc6646949dab6b3b4d5dcee7bd0.png
Contact.h:

4.2通讯录的初始化和销毁

就是对顺序表的初始化和销毁,是所以直接调用初始化和销毁函数即可。
  
//通讯录的初始化
void ContactInit(Contact* con)
{
	SLInit(con);
}

//通讯录的销毁
void ContactDesTroy(Contact* con)
{
	SLDestroy(con);
}

4.3通讯录添加数据

这里可以直接声明,联系人结构体第一局部变量,然后把数据写进去,在调用顺序表中,尾插函数,把这个结构体直接插入即可。
//通讯录添加数据
void ContactAdd(Contact* con)
{
	//获取用户输入的内容:姓名+性别+年龄+电话+地址
	peoInfo info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s", info.name);

	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);

	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);

	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);

	printf("请输入要添加的联系人住址:\n");
	scanf("%s", info.addr);

	//往通讯录中添加联系人数据
	SLPushBack(con, info);
}

4.4查找删除显⽰联系⼈信息

剩下的功能实现都要先查找到数据元素,这里写一个基于名字的查找函数函数,如果找到就把下标返回,否则返回-1。

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(con->arr[i].name, name))
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}

删除数据之前要先找到该元素,所以调用一下,上面写,查找函数FindByName。如果该下表有意义,那直接将该下表传进之前写的顺序表指定位置删除函数,就能把该数据删除了。

而顺序表的修改差不多,先找到该元素,利用下表,直接访问修改该数据就行了

//通讯录删除数据
void ContactDel(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要删除数据联系人的姓名:\n");
	scanf("%s", name);
	int ret=FindByName(con, name);
	if (ret != -1)
	{
		SLErase(con, ret);
		printf("删除成功\n");
		return;
	}
	else
		printf("该联系人不存在\n");
}

//通讯录的修改
void ContactModify(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要修改数据联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret != -1)
	{
		printf("请输入新的联系人姓名:\n");
		scanf("%s", con->arr[ret].name);

		printf("请输入新的联系人性别:\n");
		scanf("%s", con->arr[ret].gender);

		printf("请输入新的联系人年龄:\n");
		scanf("%d", &con->arr[ret].age);

		printf("请输入新的联系人电话:\n");
		scanf("%s", &con->arr[ret].tel);

		printf("请输入新的联系人住址:\n");
		scanf("%s", con->arr[ret].addr);
	}
	else
		printf("该联系人不存在\n");
}

这里查找也是先调用上面的那个查找函数FindByName。然后将要查找的数据源打印出来。
展示全部数据函数,又for循环将它们的个一个打印出来就行
//查找
int ContactFind(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要查找数据联系人的姓名:\n");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret != -1)
	{
		printf("%3s %3s %3d %3s %3s \n",
			con->arr[ret].name, 
			con->arr[ret].gender,
			con->arr[ret].age,
			con->arr[ret].tel,
			con->arr[ret].addr);
		return ret;
	}
	else
		printf("联系人不存在\n ");
	return -1;
}


void ContactShow(Contact* con)
{
	if (con->size == 0)
	{
		printf("联系人不存在\n ");
		return;
	}
	printf("%3s %3s %3s %3s %3s \n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf(" %3s  %3s  %3d  %3s  %3s \n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr);
	}

}

信息持久化,这里的调用二进制文件函数实现。

写的时候,我们是将一整块联系人数据用for循环写入。

读文件:

一边读一边调用顺序表尾插函数。就可以写入上一次的完整信息了。

//信息持久化
void SvaeContact(Contact* con)
{
	FILE* pf = fopen("Contact.txt", "wb");
	if (pf == NULL)
	{
		perror("Contact.txt\n");
		return;
	}

	peoInfo info;
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr + i, sizeof(peoInfo), 1, pf);
	}

	fclose(pf);
	pf = NULL;
}




void LoadContact(Contact* con)
{
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL)
	{
		perror("Contact.txt\n");
		return;
	}
	peoInfo info;
	while (fread(&info, sizeof(peoInfo), 1, pf) != 0)
	{
		SLPushBack(con,info);
	}
	printf("历史数据读取成功\n");

	fclose(pf);
	pf = NULL;
}

完整文件在开头,需要的自取

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

openstack基本操作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

python语言day9 正则表达式 和 xpath 解析html

正则表达式&#xff1a; 正则表达式的语法&#xff1a; 元字符&#xff1a; \D \d \w \W . [ ] 量词&#xff1a; ? * 惰性匹配&#xff1a; 玩儿(?P<name>.*?)游戏&#xff1a; 匹配到第一个游戏结束&#xff0c;name 匹配的文本。 玩儿(?P<na…

分享cesium的风场开源网站

首先是有在二维地图上的一个风场效果&#xff0c;通过canvas进行的绘制&#xff0c;例如leaflet开源地图上就能够根据数据生成风场的效果图。 最近mapbox里的大神分享了如何在cesium上实现风场的效果&#xff0c;并在github上进行了开源&#xff0c;开源地址: https://github.…

SSL Pining 问题解决方案

实战案例 为了能够更好的复现 SSL Pining 场景&#xff0c;我们对一个 App&#xff08;https:app4.scrape.center&#xff09;进行抓包&#xff0c;这个 App 包含了 SSL Pining 的相关设置&#xff0c;如果我们将手机的代理设置为抓包软件提供的代理服务&#xff0c;那么这个 …

Windows 11上RTX 4090深度学习与大模型微调环境安装指南

【本文原作者&#xff1a;擎创科技资深产品专家 布博士】 在安装深度学习及大模型微调环境时&#xff0c;经历了多次反复操作&#xff08;如CUDA、cuDNN、PyTorch的安装与卸载&#xff09;。为了避免走弯路&#xff0c;总结了以下步骤&#xff1a; 步骤 1&#xff1a;显卡驱动…

【轨物方案】直流电源屏物联网解决方案,让在线监测更简单!

流屏是保证各类变电站、水力、火力发电厂正常、安全运行的电源设备&#xff0c;也是其它使用直流设备用户(如石化、矿山、铁路、医院等)的直流电源&#xff0c;是电力系统的重要组成部分。同时直流屏在变配电中&#xff0c;发挥着很大的作用&#xff0c;它在很大程度上影响着配…

Waymo第六代无人驾驶技术亮相:更少传感器,更高效率

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【系统分析师】-综合知识-数据库基础

1、给定关系模式 R < U &#xff0c;F >&#xff0c; U {A&#xff0c;B&#xff0c;C&#xff0c;D &#xff0c;E} &#xff0c; F {B→A &#xff0c;D→A &#xff0c;A→E &#xff0c;AC→B }&#xff0c;则 R 的候选关键字为&#xff08;CD&#xff09;&#xff…

76、docker-harbor

一、docker-harbor 私有仓库部署和管理&#xff1a; docker-harbor 私有仓库部署和管理&#xff1a; harbor&#xff1a;开源的企业级的docker仓库软件。 仓库&#xff1a;私有仓库、公有仓库。私有仓库。 docker-harbor&#xff1a;是有图形化的&#xff0c;页面UI展示的一…

1.XV6环境配置

安装虚拟机 这个就不多说了&#xff0c;搞一台Ubuntu虚拟机即可&#xff0c;最好是通过vscode 用ssh远程连接进行实验会比较方便&#xff0c;具体怎么做可参考我这篇博客&#xff1a; VsCode配置SSH连接远程服务器&#xff08;手把手&#xff0c;学不会打我&#xff09;_vsco…

【Hot100】LeetCode—148. 排序链表

目录 1- 思路归并 2- 实现⭐148. 排序链表——题解思路 3- ACM 实现 原题连接&#xff1a;148. 排序链表 1- 思路 归并 1- 先求解链表的长度&#xff0c;求出长度后利用 subLen 1 开始归并 定义虚拟头结点 dummyHead &#xff0c;便于处理头结点 2- 归并逻辑 for(int subLen…

nacos 使用 docker 单机部署连接 MySQL 数据库并开启鉴权

文章目录 本地部署的配置启用鉴权(未验证) docker部署的配置修改docker 镜像源启用鉴权&#xff0c;必须添加如下环境变量如何生成鉴权的密钥 完整环境变量docker启动命令 本地部署的配置 文件结构 application.properties #配置文件 mysql-schema.sql …

[Linux#40][线程] 线程控制 | 多线程

内核中有没有很明确的线程概念呢&#xff1f;没有的。有的是轻量级进程的概念 不会给我直接提供线程的系统调用&#xff0c;只会给我们提供轻量级进程的系统调用&#xff0c;但是我们用户&#xff0c;需要线程的接口&#xff01; 所以 Linux 开发者提供了 pthread 线程库--应用…

成为创作者的第1024天:成长与技术积累的旅程

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 今天是我成为创作者的第1024天。回顾这段时间&#xff0c;虽然日常的忙碌充斥着生活…

roles(角色)

创建目录&#xff0c;编写剧本下载nginx: 184 mkdir /etc/ansible/playbook 185 vim /etc/ansible/playbook/nginx.yml --- - hosts: groupremote_user: roottasks:- name: 卸载httpdyum: namehttpd stateabsent- name: 安装nginxyum: …

【MySQL 09】复合查询 (带思维导图)

文章目录 &#x1f308; 一、准备工作&#x1f308; 二、多表查询⭐ 1. 多表笛卡尔积⭐ 2. 多表查询示例 &#x1f308; 三、自连接&#x1f308; 四、子查询⭐ 1. 标量子查询⭐ 2. 多行子查询 (需要插入其他博客的链接)⭐ 3. 多列子查询 (需要插入其他博客的链接)⭐ 4. 在 fro…

小米SU7销量超特斯拉,新车明年上半年发布

小米 SU7&#xff0c;一款国内新能源车品牌纯血新势力旗下首款轿车&#xff0c;上市短短 4 个月卖出超 4 万台&#xff0c;月均销量过万。 该说不说&#xff0c;这放在整个新能源汽车工业史上也足以称得上是一件小刀喇拍屁股&#xff0c;让人开了眼的事儿。 就在本月初&#x…

大模型在企业数智化转型中可以做哪些事情?

在数字化浪潮的推动下&#xff0c;企业数智化转型已成为不可逆转的趋势。作为人工智能技术的集大成者&#xff0c;大模型以其强大的数据处理能力、深度学习能力及广泛的应用场景&#xff0c;正逐步成为企业数智化转型的核心驱动力。 大模型&#xff1a;智能时代的基石 大模型…

Error: ReferenceError: ReadableStream is not defined

midway项目在build完&#xff0c;docker启动时&#xff0c;莫名地报错Error: ReferenceError: ReadableStream is not defined&#xff0c;之前一直好好地&#xff0c;初时以为是新加的代码引起&#xff0c;后来排除了。 报错如下&#xff1a; 2024-08-20 11:57:51.446 ERROR …

【教学类-76-01】20240820书包01(图案最大化)

背景需求 通义万相生成图片&#xff0c;把图案最大化的方法&#xff08;切掉白边&#xff09; 【教学类-75-01】20240817“通义万相图片最大化透明png”的修图流程-CSDN博客文章浏览阅读1.6k次&#xff0c;点赞56次&#xff0c;收藏17次。【教学类-75-01】20240817“通义万相…