学习笔记---不容错过的顺序表的应⽤~~


目录​​​​​​​

1. 基于动态顺序表实现通讯录项⽬

1.1 通讯录📇功能要求

1.2 总体思路分析🧐

1.3 创建+初始化+销毁顺序表🌞

1.3.1 contact.h

1.3.2 Seqlist.h

1.3.3 contact.c

1.3.4 text.c

1.3.5 代码运行测试

1.3.6 二次代码测试

1.4 添加+删除联系人👻

1.4.1 contatc.h

1.4.2 contact.c

1.4.3 tets.c

1.4.4 代码运行测试

1.5 修改联系人🙉

1.5.1 contatc.h

1.5.2 contact.c

1.5.3 tets.c

1.5.4 代码运行测试

1.5.5 contact.h优化🍎

1.5.6 test.c修改

1.5.7 二次代码运行测试

1.6 查看通讯录🥑

1.6.1 contatc.h

1.6.2 contact.c

1.6.3 tets.c

1.6.4 代码运行测试

1.7 查找指定联系人👤

1.7.1 contatc.h

1.7.2 contact.c

1.7.3 tets.c

1.7.4 代码运行测试

1.8 美观---菜单界面🏵️

1.8.1 test.c

1.9 通讯录📇代码运行测试

2. 顺序表经典算法

2.1 经典算法OJ题1: 移除元素🚨

2.1.1 题目

2.1.2 思路分析

2.1.3 代码实现

2.1.3.1 解法1

2.1.3.2 解法2

2.2 经典算法OJ题2: 合并两个有序数组☎️

2.2.2 思路分析

2.2.3 代码实现

3. 顺序表的问题及思考


1. 基于动态顺序表实现通讯录项⽬

1.1 通讯录📇功能要求

首先,我们看看通讯录需要实现什么功能:

1)⾄少能够存储100个⼈的通讯信息

2)能够保存⽤⼾信息:名字、性别、年龄、电话、地址等

3)增加联系⼈信息

4)删除指定联系⼈

5)查找制定联系⼈

6)修改指定联系⼈

7)显⽰联系⼈信息


1.2 总体思路分析🧐

首先,我们要使用上一期学习的动态顺序表实现通讯录📇,如果有不知道的小伙伴,可以移步到小江的上一篇博客:学习笔记---超基础+详细+新手的顺序表~~-CSDN博客动态顺序表的简单实现https://blog.csdn.net/2301_79184587/article/details/133842555 我们知道顺序表可以存储数据,但是通讯录存储比较多,所以我们把一个联系人的所有信息作为一个整体存储到顺序表,再进行对应接口的编写:

实现顺序表的创建,初始化,一系列具体操作,销毁

一系列具体操作:

头部/尾部增加联系⼈信息、头部/尾部删除指定联系⼈、查找制定联系⼈、指定位置修改联系⼈信息、显⽰联系⼈信息

注意⚠️

我们是在顺序表的基础上实现通讯录📇,所以我们直接在上一篇的动态顺序表的基础上实现📇



1.3 创建+初始化+销毁顺序表🌞

1.3.1 contact.h

//创建保存联系人数据的结构体
//定义联系人数据字节大小
#define NAME_MAX 100
#define SEX_MAX 10
#define PHONE_MAX 15
#define ADDR_MAX 100

typedef struct ContactInfo
{
	//采用定长数组
	char name[NAME_MAX];
	char sex[SEX_MAX] ;
	int age;
	char phone[PHONE_MAX] ;
	char addr[ADDR_MAX] ;
}CInfo;//重命名之后更加简洁方便

//通讯录的初始化和销毁
void ContactInit(contact* con);
void ContactDestroy(contact* con);

对于结构体中的数组创建是要定长数组还是动态数组?
我们使用定长数组,虽然无法确定内容大小,但是根据常识,可以给出数组的最大容量


1.3.2 Seqlist.h

注意⚠️

CInfo只是在contact.h中的结构体重命名,但是别的文件不知道有这回事,所以不认识cinfo--->我们需要包含头文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include"contact.h"//包含头文件
#include<string.h>
//创建动态顺序表
//typedef int SLDataType;//方便以后修改数据类型,因为我们不一定每次都需要int类型

//替换
typedef struct CInfo SLDataType;//注意CInfo

1.3.3 contact.c

#include"Seqlist.h"
#include"contact.h"

//通讯录的初始化和销毁
void ContactInit(contact* con)
{
	SLInit(con);//直接调用顺序表的初始化
}
void ContactDestroy(contact* con)
{
	SLDestroy(con);//直接调用顺序表的销毁
}

1.3.4 text.c

#include"Seqlist.h"
#include"contact.h"
//contact
void contact01()
{
	//创建+初始化通讯录
	contact con;
	ContactInit(&con);
	//销毁通讯录
	ContactDestroy(&con);
}
int main()
{
	contact01();
	return 0;
}

1.3.5 代码运行测试


我们发现疯狂报错,这是为什么呢?


例如我们先解决这个问题:原来的是int类型的,而新的SLDataType是struct类型的,所以==非法--->我们要修改


ps->a[I].name==x
......(一个一个比较)

这里为了方便,我们直接注释掉查找数据的相关代码


对于这个错误,我们还是把重命名修改一下,不要用CnInfo了(contact.h)

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include"contact.h"//包含头文件
//创建动态顺序表
//typedef int SLDataType;//方便以后修改数据类型,因为我们不一定每次都需要int类型

//替换
typedef struct ContactInfo SLDataType;

1.3.6 二次代码测试


1.4 添加+删除联系人👻

1.4.1 contatc.h

//添加+删除联系人
void ContactAdd(contact* pcon);
void ContactcDel(contact* pcon);

1.4.2 contact.c

//添加联系人
void ContactAdd(contact* pcon)
{
	//接下来要获取的数据都是CInfo结构体里我们设置的数据
	CInfo info;
	printf("请输入要添加的联系人的姓名:");
	scanf("%s", info.name);//name是数组名--->本来就是地址
	printf("请输入请输入要添加的联系人的性别:");
	scanf("%s", info.sex);
	printf("请输入要添加的联系人的年龄:");
	scanf("%d", &info.age);//age是int类型的数据--->取地址
	printf("请输入要添加的联系人的号码:");
	scanf("%s", info.phone);
	printf("请输入要添加的联系人的地址:");
	scanf("%s", info.addr);
	//数据获取到之后存储到info中
	//接下来,我们需要在顺序表中插入数据
	SLpushBack(pcon, info);//直接调用顺序表的尾插
}

//删除联系人
//由于删除/添加/查找联系人都需要判断联系人是否存在,所以我们把判断联系人是否存在单独写出来
int FindByName(contact* pcon, char name[])
{
	for (int i = 0; i < pcon->size; i++)
	{ 
		if (strcmp(pcon->a[i].name, name) == 0)//strcmp比较字符串大小
			return i;
	}
	return -1;
}

void ContactcDel(contact* pcon)
{
	//我们需要使用联系人众多信息中的一项来查找联系人是否存在
	//这里直接要求输入联系人的姓名进行查找
	printf("请输入要删除的联系人的姓名:");
	//创建一个name数组存储要输入的姓名
	char name[NAME_MAX];
	scanf("%s", name);
	//调用函数判断联系人是否存在
	//1.存在--->根据返回的下标删除--->即为调用顺序表的删除指定位置的数据
	//2.不存在--->说明要删除的联系人不存在
	int ret=FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要求删除的联系人不存在!\n");
		return 1;
	}
	else
	{
		SLErase(pcon, ret);//调用顺序表的删除指定位置的数据
	}
}

1.4.3 tets.c

#include"Seqlist.h"
#include"contact.h"
//contact
void contact01()
{
	//创建+初始化通讯录
	contact con;
	ContactInit(&con);
	//添加联系人
	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	//删除联系人
	ContactcDel(&con);
	//销毁通讯录
	ContactDestroy(&con);
}
int main()
{
	contact01();
	return 0;
}

1.4.4 代码运行测试


1.5 修改联系人🙉

1.5.1 contatc.h

//修改联系人
void ContactChange(contact* pcon);

1.5.2 contact.c

//修改联系人
void ContactChange(contact* pcon)
{
	//我们需要使用联系人众多信息中的一项来查找联系人是否存在
    //这里直接要求输入联系人的姓名进行查找
	//创建一个name数组存储要输入的姓名
	char name[NAME_MAX];
	printf("请输入要修改的联系人的姓名:");
	scanf("%s", name);
	//调用函数判断联系人是否存在
//1.存在--->根据返回的下标修改
//2.不存在--->说明要修改的联系人不存在
	int ret = FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要求修改的联系人不存在!\n");
		return 1;
	}
	else
	{
		//底层逻辑是顺序表--->在顺序表中修改对应的下标的结构体中的各项数据
		printf("请输入新的联系人的姓名:");
		scanf("%s", pcon->a[ret].name);//name是数组名--->本来就是地址
		printf("请输入请输入新的联系人的性别:");
		scanf("%s", pcon->a[ret].sex);
		printf("请输入新的联系人的年龄:");
		scanf("%d", &pcon->a[ret].age);//age是int类型的数据--->取地址
		printf("请输入新的联系人的号码:");
		scanf("%s", pcon->a[ret].phone);
		printf("请输入新的联系人的地址:");
		scanf("%s", pcon->a[ret].addr);
		printf("修改成功!\n");
	}
}

1.5.3 tets.c

#include"Seqlist.h"
#include"contact.h"
//contact
void contact01()
{
	//创建+初始化通讯录
	contact con;
	ContactInit(&con);
	//添加联系人
	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	//删除联系人
	ContactDel(&con);
	//修改联系人
	ContactChange(&con);
	//销毁通讯录
	ContactDestroy(&con);
}
int main()
{
	contact01();
	return 0;
}

1.5.4 代码运行测试


但是,我们发现有时候修改联系人的时候,我们可能只需要修改年龄or地址单个数据,或者几个数据,不是全都要修改,所以要优化一下啊

1.5.5 contact.h优化🍎

我们可以添加菜单,让使用者选择要修改的项目,在原来的代码基础上修改,从而达到只修改1项或者几项的目的


//修改联系人
void ContactChange(contact* pcon)
{
	//我们需要使用联系人众多信息中的一项来查找联系人是否存在
	//这里直接要求输入联系人的姓名进行查找
	//创建一个name数组存储要输入的姓名
	char name[NAME_MAX];
	printf("请输入要修改的联系人的姓名:");
	scanf("%s", name);
	//调用函数判断联系人是否存在
//1.存在--->根据返回的下标修改
//2.不存在--->说明要修改的联系人不存在
	int ret = FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要求修改的联系人不存在!\n");
		return 1;
	}
	else
	{
		int a = -1;
		do {
			printf("*******************************************\n");
			printf("*******************通讯录******************\n");
			printf("***********1.修改姓名 2.修改性别***********\n");
			printf("***********3.修改年龄 4.修改号码***********\n");
			printf("***********5.修改地址 6.退出修改***********\n");
			printf("请选择你的操作:\n");
			scanf("%d", &a);
			//底层逻辑是顺序表--->在顺序表中修改对应的下标的结构体中的各项数据
			switch (a)
			{
			case 1:
				printf("请输入新的联系人的姓名:");
				scanf("%s", pcon->a[ret].name);//name是数组名--->本来就是地址
				break;
			case 2:
				printf("请输入请输入新的联系人的性别:");
				scanf("%s", pcon->a[ret].sex);
				break;
			case 3:
				printf("请输入新的联系人的年龄:");
				scanf("%d", &pcon->a[ret].age);//age是int类型的数据--->取地址
				break;
			case 4:
				printf("请输入新的联系人的号码:");
				scanf("%s", pcon->a[ret].phone);
				break;
			case 5:
				printf("请输入新的联系人的地址:");
				scanf("%s", pcon->a[ret].addr);
				break;
			case 6:
				printf("退出修改联系人的界面!\n");
				break;
			default:
				printf("输入有误!请重新输入:\n");
				break;
			}
		} while (a != 6);
	}
}

1.5.6 test.c修改

#include"Seqlist.h"
#include"contact.h"
//contact
void contact01()
{
	//创建+初始化通讯录
	contact con;
	ContactInit(&con);
	//添加联系人
	ContactAdd(&con);
	//ContactAdd(&con);
	ContactAdd(&con);
	//删除联系人
	//ContactDel(&con);
	//修改联系人
	ContactChange(&con);
	//销毁通讯录
	ContactDestroy(&con);
}
int main()
{
	contact01();
	return 0;
}

为了方便,我们就先注释掉删除联系人的操作,并且只添加2个联系人


1.5.7 二次代码运行测试


1.6 查看通讯录🥑

1.6.1 contatc.h

//查看通讯录
void ContactShow(contact* pcon);

1.6.2 contact.c

//查看通讯录
void ContactShow(contact* pcon)
{
	//打印通讯录存储的所有数据
	//为了更加好看--->我们先输出表头
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "号码", "地址");
	for (int i = 0; i < pcon->size; i++)
	{
		printf("%-4s %-4s %-4d %-4s %-10s\n",//表头对齐--->美观
			pcon->a[i].name,
			pcon->a[i].sex,
			pcon->a[i].age,
			pcon->a[i].phone,
			pcon->a[i].addr
			);
	}
}

1.6.3 tets.c

#include"Seqlist.h"
#include"contact.h"
//contact
void contact01()
{
	//创建+初始化通讯录
	contact con;
	ContactInit(&con);
	//添加联系人
	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	//删除联系人
	ContactDel(&con);
	//修改联系人
	ContactChange(&con);
	//查看通讯录
	ContactShow(&con);
	//销毁通讯录
	ContactDestroy(&con);
}

int main()
{
	contact01();
	return 0;
}

1.6.4 代码运行测试


1.7 查找指定联系人👤

1.7.1 contatc.h

//查找指定联系人
void ContactFind(contact* pcon);

1.7.2 contact.c

//查找指定联系人
void ContactFind(contact* pcon)
{
//我们需要使用联系人众多信息中的一项来查找联系人是否存在
//这里直接要求输入联系人的姓名进行查找
//创建一个name数组存储要输入的姓名
	char name[NAME_MAX];
	printf("请输入要查找的联系人的姓名:");
	scanf("%s", name);
	//调用函数判断联系人是否存在
//1.存在--->根据返回的下标查找并打印出来
//2.不存在--->说明要查找的联系人不存在
	int ret = FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要求查找的联系人不存在!\n");
		return 1;
	}
	else
	{
		printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "号码", "地址");
			printf("%-4s %-4s %-4d %-4s %-4s\n",//表头对齐--->美观
				pcon->a[ret].name,
				pcon->a[ret].sex,
				pcon->a[ret].age,
				pcon->a[ret].phone,
				pcon->a[ret].addr
			);
	}
}

1.7.3 tets.c

#include"Seqlist.h"
#include"contact.h"
//contact
void contact01()
{
	//创建+初始化通讯录
	contact con;
	ContactInit(&con);
	//添加联系人
	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	//删除联系人
	ContactDel(&con);
	//修改联系人
	ContactChange(&con);
	//查看通讯录
	ContactShow(&con);
	//查找指定联系人
	ContactFind(&con);
	//销毁通讯录
	ContactDestroy(&con);
}


int main()
{
	contact01();
	return 0;
}

1.7.4 代码运行测试


1.8 美观---菜单界面🏵️

为了更加美观,我们制作一个菜单界面


1.8.1 test.c

//为了界面更加美观--->创建菜单界面
void menu1()
{
	printf("***********************************************\n");
	printf("*********************通讯录********************\n");
	printf("***********1.添加联系人 2.删除联系人***********\n");
	printf("***********3.修改联系人 4.查找联系人***********\n");
	printf("***********5.查看通讯录 6.退出通讯录***********\n");
}
int main()
{
	int a = -1;
	//初始化+创建通讯录
	contact con;
	ContactInit(&con);
	//一系列操作
	do {
		menu1();
		printf("请选择你的操作:\n");
		scanf("%d", &a);
		switch (a)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactChange(&con);
			break;
		case 4:
			ContactShow(&con);
			break;
		case 5:
			ContactFind(&con);
			break;
		case 6:
			printf("退出通讯录界面!\n");
			break;
		default:
			printf("选择错误!请重新选择:\n");
			break;
		}
	} while (a != 6);
		//销毁通讯录
		ContactDestroy(&con);
	return 0;
}

1.9 通讯录📇代码运行测试


2. 顺序表经典算法

2.1 经典算法OJ题1: 移除元素🚨

2.1.1 题目


2.1.2 思路分析

解法1:遍历一遍数组,若值为val,执行删除操作

​​​​​​​


解法2:使用双指针

定义2个指针src=0和dst=0遍历数组

1)src指向的数据是val

src++;

2)src指向的数据不是val

src指向的数据赋给dst的位置

dst++;

src++;


2.1.3 代码实现

2.1.3.1 解法1
int removeElement(int* nums, int numsSize, int val){
int size=0;
for(int i=0;i<numsSize;i++)
{
if(nums[i]!=val)
{
    nums[size++]=nums[i];
}
}
return size;
}

2.1.3.2 解法2
int removeElement(int* nums, int numsSize, int val){
int src=0,dst=0;
while(src<numsSize)
{
    if(nums[src]==val)
    src++;
    else
    {
        nums[dst]=nums[src];
        dst++;
        src++;
    }
}
return dst;
}

2.2 经典算法OJ题2: 合并两个有序数组☎️

2.2.1 题目


2.2.2 思路分析



2.2.3 代码实现

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int l1=m-1,l2=n-1;
int l3=m+n-1;
while(l1>=0&&l2>=0)
{
    if(nums1[l1]>nums2[l2])
    nums1[l3--]=nums1[l1--];
    else
    {
        nums1[l3--]=nums2[l2--];
    }
}
while(l2>=0)
{
    nums1[l3--]=nums2[l2--];
}
}

3. 顺序表的问题及思考

1. 中间/头部的插⼊删除,时间复杂度为O(N) 

2. 增容需要申请新空间,拷⻉数据,释放旧空间。会有不⼩的消耗。

3. 增容⼀般是呈2倍的增⻓,势必会有⼀定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插⼊了5个数据,后⾯没有数据插⼊了,那么就浪费了95个数据空间。

思考:如何解决以上问题呢?


http://www.niftyadmin.cn/n/5106421.html

相关文章

Vue-vue项目Element-UI 表单组件内容要求判断

整体添加判断 <el-formref"ruleFormRef":model"formModel"class"demo-ruleForm"label-position"top"status-icon:rules"rules"><el-form-item label"姓名" prop"applyUsers" class"form-…

Vue实现双向数据绑定的4个方法

一:使用 v-model 指令实现双向数据绑定 使用 v-model 指令可以很方便地实现双向数据绑定。以下是使用 v-model 指令实现双向数据绑定的步骤: 在 Vue 实例中定义一个数据属性。 <template><input v-model="message" type="text"><p>…

CUDA编程- 瓦片(Tiling)技术

瓦片&#xff08;Tiling&#xff09;技术是CUDA编程中的一个常见策略&#xff0c;用于优化内存访问模式&#xff0c;特别是在矩阵乘法这类计算密集型操作中。 1. 基本概念 当我们说“瓦片”时&#xff0c;我们指的是将大数据集&#xff08;如矩阵&#xff09;划分为较小的块或…

串口应用层程序

文章目录 注意两点&#xff1a;一、设置原始模式二、设置收到数据的最小字节数返回代码 注意两点&#xff1a; 一、设置原始模式 newtio.c_lflag & ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/二、设置收到数据的最小字节数返回 tio.c_cc[VMIN] 1; /* 读数据时的最…

丈母娘说:有编制的不如搞编程的

10月17日百度世界大会召开&#xff0c;据说文心大模型又牛X了&#xff0c;综合水平相比GPT4毫不逊色&#xff0c;真是个让人激动的消息&#xff0c;国产大模型的进展可以说是日新月异&#xff0c;我这耳朵边一直响彻四个字&#xff1a;遥遥领先。 不过今天我关注的重点不是什么…

电脑入门:电脑硬件入门到精通

搞清内存常见问题及解决方案 内存做为电脑三大件配件之一,担负着数据的临时存取等任务。在使用过程中,难免会出现一些问题,如启动电脑却无法正常启动、无法进入操作系统或运行应用软件、无故经常死机等故障,这些问题的产生常会因为内存出现异常故障而导致操作失败。内存出现…

Vant Weapp的Slider组件自定义button

js部分: <van-slider v-model"value" range drag"priceChange" drag-end"sliderDragEnd" use-button-slot max"1000" min"0" step"10"><view class"custom-button" slot"left-button&…

Note——time

time import import datetime import timeDefinition of time from 1970-01-01 00:00:00 UTC Coordinated Universal Time as the float format of ‘seconds’ For example use structured time lists [ year,month,day,hours,minutes,seconds…] 表示从1970-01-01 00:00:…