【数据结构】顺序表-元素去重

news2025/4/2 10:28:59
  1. 数据元素

结点定义,复杂数据类型,可用作整体性的管理系统。如果单独研究某些数据,比如只看学号或成绩,那么直接使用int之类的简单数据类型亦可。对应修改:typedef int Elemtype;

typedef struct student{ 	//定义学生个体 
	char name[100];	//姓名 
	int num;		//学号 
} Student;

typedef Student Elemtype;

使用Elemtype做数据类型,对应修改为其他数据时更加便捷,增强代码复用性。

  1. 顺序表定义

整体性思维,顺序表整体包含数据部分和长度两个属性。数据部分采用指针的方式指向首个元素的地址,通过下标的方式进行访问与使用。

typedef struct { 	//定义顺序表的数据结构
	Elemtype *p;	//线性表首地址  
	int length;		//当前的长度  
} SeqList; 
  1. 初始化顺序表

为顺序表申请存储空间,成功后将表长度属性置0。注意C语言调用函数malloc申请,free进行释放,需加头文件。C++使用new与delete进行释放。

#include <stdlib.h>
// C语言
L.p = (Elemtype *)malloc(sizeof(Elemtype) * MAXSIZE);  
free(L.p);

// C++写法
L.p=new Elemtype[MAXSIZE];			
delete L.p;

//初始化线性表  
int InitList(SeqList &L) {  //为顺序表的元素分配内存空间,大小为100个int的大小

	L.p = (Elemtype *)malloc(sizeof(Elemtype) * MAXSIZE);  
	if(!L.p)
		exit(0);		//overflow  分配失败
	L.length = 0;		//初始表长度为0
    return 0;  
}
  1. 顺序表插入元素

向第k个位置插入元素,那么对于长度为L.length的顺序表,可以插入的位置为1-L.length,所以判断非法位置时以此判断。

插入元素注意每个元素需往后挪一个位置,最后把k号位空出来。注意:必须先挪后面的元素,否则元素覆盖将出现数据丢失。

最后由于插入元素,顺序表长度++;

//向表尾插入元素  
void InsertList(SeqList &L,Elemtype e) {  

	if(L.length >= MAXSIZE)  //判断当前的顺序表是不是已经满了
		return ;
	L.p[L.length]=e;  		//如果没有满,就在顺序表的后面添加元素e
	L.length++;  			//添加后顺序表长度+1
	return;  
}

//向第k个位置插入元素  
void InsertList_k(SeqList &L,int k,Elemtype e) {  

	if(L.length >= MAXSIZE)  //判断当前的顺序表是不是已经满了
		return ;
	if(k<1||k>L.length+1)	//插入位置不合法 
		return ; 
	for(int j=L.length;j>=k;j--)
		L.p[j]=L.p[j-1];
	L.p[k-1]=e;
	L.length++;  			//添加后顺序表长度+1
	return;  
}
  1. 遍历顺序表

循环一次遍历即可。倘若访问第k个位置,那么由于顺序表的特性(逻辑相邻,存储也相邻,可通过计算直接进行访问),通过下标即可访问对应位置。

Elemtype e=L.p[k-1];
//遍历顺序表  
void PrintList(SeqList &L) {  

	int i;  
	for(i=0;i<L.length;i++) { //循环遍历打印
		printf("[ %s - %d ] \n",L.p[i].name,L.p[i].num);  
	}  
	printf("\n");  
	return;  
}
  1. 删除元素

1)删除第k个元素,需要把元素往向前移动,以保证逻辑相邻,存储上依旧相邻。

2)删除顺序表中的重复元素:4种策略
①桶排序,具有去重效果,取数时只取一次;
②先排序,再对相邻元素进行去重;
③申请额外的空间,依次访问原始顺序表中的元素,与新表中元素不重复即存到末端。
④分别取每一个元素,将后续表中所有重复元素进行删除处理。

方法1,2去重后有序。方法3,4去重后数据相对位置不变
假设顺序表数据元素个数为n,数据取值范围为m。

方法1时间复杂度O(n),空间复杂度O(m)。----受限于数据元素的取值范围,因为需要准备那么多个‘桶’。
方法2时间复杂度O(nlogn),空间复杂度O(1)。----排序采用O(nlogn)的算法,去重时可以考虑双指针,i指向当前处理的数据,j单独记录非重复元素个数,i向后移动直到元素不重复,将i位置元素移动到j的位置,并j++。时间复杂度为O(1)。
方法3时间复杂度O(n^2),空间复杂度O(n)。----双层循环比较原始顺序表与新顺序表中的每一个元素是否相同。
方法4时间复杂度O(n^3),空间复杂度O(1)。----双层循环寻找重复元素位置,额外一层循环用于删除元素后的移动操作。

 //删除第k个元素 
void Delete_k(SeqList &L,int k) {  

	if(k<1||k>L.length)	//删除位置不合法 
		return ; 
	for(int j=k-1;j<L.length-1;j++)
		L.p[j]=L.p[j+1];
	L.length--;  			//删除后顺序表长度-1
	return;  
}
       
//删除重复值 
void Deletep(SeqList &L) {
	
	int i,j;
	int temp; 
	for(i=0;i<L.length-1;++i) {		//循环整个顺序表
		for(j=i+1;j<L.length;j++)	//每次判断当前元素和它之后的所有元素是否重复
			if(L.p[i].num==L.p[j].num) {
				//如果有与i相同的元素j,则j后面的所有的元素往前一位,覆盖掉j
				for(int k=j;k<L.length;k++)
					L.p[k]=L.p[k+1];
				L.length--; 
				j--;
			}
	}   
}  
  1. 查找元素

查找方式:序号查找,按元素值进行查找。
按元素查找,需要遍历顺序表,依次比较,时间复杂度为O(n)。

//查找第k个元素 
void find_k(SeqList L,int k, Elemtype &e) {  
	if(k<1||k>L.length)	//查找位置不合法 
		return ; 
	e=L.p[k-1]; 
	return;  
}

//查找元素e的位置 
int find_e(SeqList L,Elemtype e) {  
	for(int i=0;i<L.length;i++)		//循环整个顺序表
		if(L.p[i].num==e.num) 
			return i+1;  
}
  • 完整代码:
#include <stdio.h>  
#include <stdlib.h>  
#define MAXSIZE 100
//线性顺序表  
typedef struct student{ 	//定义学生个体 
	char name[100];	//姓名 
	int num;		//学号 
} Student;

typedef Student Elemtype;

typedef struct { 	//定义顺序表的数据结构
	Elemtype *p;	//线性表首地址  
	int length;		//当前的长度  
} SeqList;  

//初始化线性表  
int InitList(SeqList &L) {  //为顺序表的元素分配内存空间,大小为100个int的大小

	L.p = (Elemtype *)malloc(sizeof(Elemtype) * MAXSIZE);  
	if(!L.p)
		exit(0);		//overflow  分配失败
	L.length = 0;		//初始表长度为0
    return 0;  
}

//向表尾插入元素  
void InsertList(SeqList &L,Elemtype e) {  

	if(L.length >= MAXSIZE)  //判断当前的顺序表是不是已经满了
		return ;
	L.p[L.length]=e;  		//如果没有满,就在顺序表的后面添加元素e
	L.length++;  			//添加后顺序表长度+1
	return;  
}

//向第k个位置插入元素  
void InsertList_k(SeqList &L,int k,Elemtype e) {  
	if(L.length >= MAXSIZE)  //判断当前的顺序表是不是已经满了
		return ;
	if(k<1||k>L.length+1)	//插入位置不合法 
		return ; 
	for(int j=L.length;j>=k;j--)
		L.p[j]=L.p[j-1];
	L.p[k-1]=e;
	L.length++;  			//添加后顺序表长度+1
	return;  
}

//遍历顺序表  
void PrintList(SeqList &L) {  

	int i;  
	for(i=0;i<L.length;i++) { //循环遍历打印
		printf("[ %s - %d ] \n",L.p[i].name,L.p[i].num);  
	}  
	printf("\n");  
	return;  
}

//删除第k个元素 
void Delete_k(SeqList &L,int k) {  

	if(k<1||k>L.length)	//删除位置不合法 
		return ; 
	for(int j=k-1;j<L.length-1;j++)
		L.p[j]=L.p[j+1];
	L.length--;  			//删除后顺序表长度-1
	return;  
}
       
//删除重复值 
void Deletep(SeqList &L) {
	
	int i,j;
	int temp; 
	for(i=0;i<L.length-1;++i) {		//循环整个顺序表
		for(j=i+1;j<L.length;j++)	//每次判断当前元素和它之后的所有元素是否重复
			if(L.p[i].num==L.p[j].num) {
				//如果有与i相同的元素j,则j后面的所有的元素往前一位,覆盖掉j
				for(int k=j;k<L.length;k++)
					L.p[k]=L.p[k+1];
				L.length--; 
				j--;
			}
	}   
}  

//查找第k个元素 
void find_k(SeqList L,int k, Elemtype &e) {  
	if(k<1||k>L.length)	//查找位置不合法 
		return ; 
	e=L.p[k-1]; 
	return;  
}

//查找元素e的位置 
int find_e(SeqList L,Elemtype e) {  
	for(int i=0;i<L.length;i++)		//循环整个顺序表
		if(L.p[i].num==e.num) 
			return i+1;  
}

int main() {
	
	SeqList list;		//定义变量
	InitList(list);		//初始化线性表list,对list进行修改,这里是值传递
	int n;  			//定义要存放的数的个数
	scanf("%d",&n);		//输入n的值
	int i;
	Student temp;  
	for(i=0;i<n;i++) { //循环给顺序表输入数值
		scanf("%d",&temp.num);
		scanf("%s",temp.name);
//		InsertList_k(list,1,temp);		// 输入数据后逆序存储,相当于前插法
		InsertList_k(list,list.length+1,temp);	//输入数据顺序存储,相当于后插法
	}
	
	Deletep(list) ;//删除冗余数值
	
	printf("顺序表长度:%d\n",list.length);//打印删除后的顺序表的长度
	PrintList(list);//打印顺序表

    return 0;  
}  

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

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

相关文章

element-plus中,Loading 加载组件的使用

一.基本使用 给一个组件&#xff0c;如&#xff1a;table表格&#xff0c;加上v-loading"true"即可。 举例&#xff1a;复制如下代码。 <template><el-table v-loading"loading" :data"tableData" style"width: 100%"><…

Mybatis_Plus中的常用注解

目录 1、TableName TableId TableId的type属性 TableField 1、TableName 经过以上的测试&#xff0c;在使用MyBatis-Plus实现基本的CRUD时&#xff0c;我们并没有指定要操作的表&#xff0c;只是在 Mapper接口继承BaseMapper时&#xff0c;设置了泛型User&#xff0c;而操…

高并发金融系统,“可观测-可追溯-可回滚“的闭环审计体系

一句话总结 在高并发金融系统中&#xff0c;审计方案设计需平衡"观测粒度"与"系统损耗"&#xff0c;通过双AOP实现非侵入式采集&#xff0c;三表机制保障操作原子性&#xff0c;最终形成"可观测-可追溯-可回滚"的闭环体系。 业务痛点与需求 在…

企业内训|DeepSeek技术革命、算力范式重构与场景落地洞察-某头部券商

3月19日北京&#xff0c;TsingtaoAI公司负责人汶生受邀为某证券公司管理层和投资者举办专题培训&#xff0c;围绕《DeepSeek技术革命、算力范式重构与场景落地洞察》主题&#xff0c;系统阐述了当前AI技术演进的核心趋势、算力需求的结构性变革&#xff0c;以及行业应用落地的关…

VS Code C/C++项目设置launch.json中的environment参数解决支持库路径问题

问题描述 Windows 11 VS Code C/C 开发环境搭建分别写了c和cpp两个示例代码&#xff0c;在运行过程中c代码没有发现问题&#xff08;可能简单&#xff0c;没有用到太多支持&#xff09;&#xff0c;但使用了stl的cpp代码并没有运行出来&#xff0c;如下图&#xff1a; 出问题…

怎样解决 Windows 11 上的 DirectX 错误,最新DX 问题解决方法

在使用 Windows 11 操作系统的过程中&#xff0c;大家可能会遇到 DirectX 错误的情况&#xff0c;这可能会给游戏体验、多媒体应用甚至是系统的整体性能带来负面影响。不过别担心&#xff0c;本文将为大家详细介绍如何解决 Windows 11 上的 DirectX 错误&#xff0c;让您的系统…

PH热榜 | 2025-03-30

1. Deepcord 标语&#xff1a;Discord 数据分析&#xff1a;获取指标洞察与受众研究 介绍&#xff1a;Deepcord&#xff1a;为社区建设者提供的Discord分析工具。跟踪超过50万个服务器的指标&#xff0c;发现热门社区&#xff0c;监控竞争对手&#xff0c;找到你的目标受众。…

Open webui的使用

问题 之前本地量化模型管理器ollama的文章&#xff0c;我们知道可以通过ollama来管理本地量化模型&#xff0c;也能够在命令行中与相关模型进行对话。现在我们想要在有个web页面通过浏览器来与本地模型对话。这里我们就使用Open webui作为界面来与本地模型对话。 安装启动 这…

STM32单片机的桌面宠物机器人(基于HAL库)

效果 基于STM32单片机的桌面宠物机器人 概要 语音模块&#xff1a;ASR PRO&#xff0c;通过天问block软件烧录语音指令 主控芯片&#xff1a;STM32F103C8T6 使用HAL库 屏幕&#xff1a;0.96寸OLED屏&#xff0c;用来显示表情 4个舵机&#xff0c;用来当作四只腿 底部一个面…

Ubuntu 22 Linux上部署DeepSeek R1保姆式操作详解(ollama方式)

操作系统&#xff1a;Ubuntu Linux 22.04 一、安装模型运行环境 打开链接https://ollama.com/download/linux 1.安装ollama &#xff08;1&#xff09;一条指令即可实现的简易版安装方法&#xff08;也可称为在线安装&#xff09; curl -fsSL https://ollama.com/install.s…

深度学习处理时间序列(6)

RNN的高级用法 循环dropout&#xff08;recurrent dropout&#xff09;​&#xff1a;这是dropout的一种变体&#xff0c;用于在循环层中降低过拟合。 循环层堆叠&#xff08;stacking recurrent layers&#xff09;​&#xff1a;这会提高模型的表示能力&#xff08;代价是更…

【鸿蒙5.0】向用户申请麦克风授权

#效果图 步骤 在 config.json 里声明权限&#xff1a;在项目的 config.json 文件中添加麦克风权限的声明&#xff0c;告知系统应用需要使用该权限。检查权限状态&#xff1a;在代码里检查应用是否已经获得了麦克风权限。请求权限&#xff1a;若应用未获得麦克风权限&#xff0…

【解决】导入PNG图片,转 Sprite 格式成功但资产未生效问题

开发平台&#xff1a;Unity 6.0 图片格式&#xff1a;.png   问题描述 当 PNG 成功转换为 Sprite&#xff08;精灵&#xff09;时&#xff0c;资产状态将显示扩展箭头&#xff0c;即表明该资产可 Sprite 使用。 解决方法&#xff1a;设置正确的 Sprite Mode Single 关于 Spr…

从DeepSeek到Qwen,AI大模型的移植与交互实战指南

在不久前发布的《技术实战 | OK3588-C开发板上部署DeepSeek-R1大模型的完整指南》一文中&#xff0c;小编为大家介绍了DeepSeek-R1在飞凌嵌入式OK3588-C开发板上的移植部署、效果展示以及性能评测&#xff0c;本篇文章不仅将继续为大家带来关于DeepSeek-R1的干货知识&#xff0…

SkyWalking+Springboot实战

1、下载SkyWalking APM 1.手动下载 Downloads | Apache SkyWalkinghttps://skywalking.apache.org/downloads/ 2.链接下载 https://dlcdn.apache.org/skywalking/10.2.0/apache-skywalking-apm-10.2.0.tar.gzhttps://dlcdn.apache.org/skywalking/10.2.0/apache-skywalking-…

org.apache.maven.surefire:surefire-junit-platform:jar:2.22.2 Maven打包失败

org.apache.maven.surefire:surefire-junit-platform:jar:2.22.2 解决办法 勾上这个&#xff0c;打包时跳过测试代码

在机器人和无人机时代,测绘人的出路在哪里?

一、技术革命&#xff1a;当测绘行业按下“加速键” 无人机与机器人技术正在重塑测绘行业的底层逻辑。传统测绘依赖人工作业&#xff0c;效率低、成本高且风险大&#xff0c;而无人机凭借其灵活性和高效性&#xff0c;已能快速完成大范围地形测绘&#xff0c;精度可达厘米级&a…

linux》》docker 、containerd 保存镜像、打包tar、加载tar镜像

Linux》》docker: 默认情况下&#xff0c;Docker镜像保存在/var/lib/docker/目录下。 当您使用docker pull命令从Docker Hub或私有镜像仓库中拉取镜像时&#xff0c;Docker会自动将镜像文件保存在/var/lib/docker/image/目录下。 每个镜像都由一个或多个层组成&#xff0c;这些…