数组去重(c语言实现)

起因

在九度练习acm的时候,有道题我认为应该先进行数组去重操作,由于工作中我大部分都是用php写代码,php中数组去重只要一个array_diff()函数即可实现,但是到C语言中,我就没有现成的api函数可以让我调用了,因此我自己实现了一个算法,进行数组去重,但是这个算法有明显的缺陷,我会先把算法展示出来,然后解释算法的缺陷

数组去重代码

#include <stdio.h>
#include <stdlib.h>

#define false -1

int arraydiff(int *A, int max, int len);

int main()
{
	int a[100];
	int n, k, i, len, max;

	while(scanf("%d",&n) != EOF)
	{
		//接收客户端数据
		for(i = 0; i < n; i ++)
		{
			scanf("%d",&a[i]);
		}
		scanf("%d",&k);

		//找到a[i]的最大数
		max = a[0];
		for(i = 1; i < n; i ++)
		{
			if(max < a[i])
				max = a[i];
		}

		//数组去重加由小到大排序
		len = arraydiff(a, max, n);
		
		//输出第K大的数
		printf("%d\n",a[k - 1]);
	}

	return 0;
}

/**
 * Description:数组去重算法
 */
int arraydiff(int *A, int max, int len)
{
	int arrayflag[max + 1];
	int i, j;

	//初始化标志数组
	for(i = 0; i <= max; i ++)
	{
		arrayflag[i] = false;
	}

	//剔除算法
	for(i = 0; i < len; i ++)
	{
		arrayflag[A[i]] = A[i];
	}

	//取出有效数
	for(i = 0, j = 0; i <= max; i ++)
	{
		if(arrayflag[i] != false)
		{
			A[j ++] = arrayflag[i];
		}
	}
	return j;
}

缺陷

因为该算法需要重新申请数组空间,而数组空间的大小则是以去重数组中的最大数为标准,这样就会出现很极端的情况,我的数组int A[4] = {112000,11200,1,2},尽管需要去重的数组A大小为4,我却要重新申请112000大小的新的内存空间,这是极大的浪费

需求

希望大家能给我回帖,写出您认为比较好的数组去重算法,建议代码最好用C实现,凡是给我留言者,我必定回复
<think>首先,用户查询是:“我想查找在C语言实现数组的方法 请问C语言实现数组的方法”。这是在询问如何在C语言实现数组。 根据系统级指令,我需要: - 使用中文回答。 - 在行内数学表达式中使用 `$...$`。 - 独立公式使用 `$$...$$`。 - 语法正确。 - 生成相关问题。 - 在引用的段落末尾添加引用标识 [^1]。 用户提到了一个引用:[1]:C语言实现数组。... [^1]。但指令说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 用户上一次的问题是什么?在这个会话中,用户的上一次查询就是这个关于数组的请求。 从上下文看,用户说:“参考站内引用:引用[1]:...”,但指令强调这仅供参考,我应该专注于用户当前的查询:“我想查找在C语言实现数组的方法”。 我的回答需要结构化,帮助用户逐步解决问题。 关键部分是实现数组。 在C语言中,数组的一个常见方法是: 1. 在原数组上操作或创建一个新数组。 2. 遍历数组元素。 3. 对于每个元素,检查它是否已经在新数组或已处理的部分中。 4. 如果不存在,则添加它。 一个高效的实现可能涉及排序数组,然后移除复元素,因为排序后复元素会相邻。 但我需要提供代码示例。 在之前的系统指令示例中,有一个Python快速排序的代码块,所以我应该提供一个C语言的代码块。 参考引用中提到:“定义一个新数组或在原数组上操作;遍历原数组,对每个元素与新数组中的元素进行比较;若新数组中无此元素,则将其添加到新数组中;最后得到的新数组即为后的数组。” 这描述了基本方法,但效率不高,因为对每个元素都需要扫描新数组,复杂度O(n^2)。 我可以描述一个更好的方法,比如先排序。 为了回答可靠,我应该提供简单的方法,并提及优化。 步骤: 1. 解释基本方法。 2. 提供代码示例。 3. 讨论优化。 4. 生成相关问题。 回答结构: - 介绍数组的概念。 - 描述实现步骤。 - 提供C语言代码。 - 解释代码。 - 添加相关问题。 引用标识:既然用户提到了引用[1],我应该引用它,但指令说“仅供参考”,所以或许在解释时提到。 指令说:“回答中引用的段落末尾自然地添加引用标识”,意思是如果我直接引用内容,就添加[^1]。 在用户提供的引用中,有[^1],所以我需要在引用时使用它。 但在我的回答中,我可以基于这个描述。 最后,生成相关问题。 现在,关于数学表达式:数组可能不涉及数学,但如果有的话添加。例如,复杂度可以是O(n^2)或O(n log n)。 例如,在讨论复杂度时,使用行内数学:$O(n^2)$ 或 $O(n \log n)$。 代码块:使用类似示例中的格式。 ```c // code here ``` 完整回答: 1. 开头:介绍方法。 2. 描述一种简单方法(基于引用)。 3. 提供代码。 4. 讨论缺点和优化。 5. 相关问题。 </think>### C语言实现数组的方法 数组是指在数组中移除复的元素,保留唯一值。在C语言中,实现数组有多种方法,包括在原数组上操作或创建新数组。以下我将详细介绍一种基本的实现方法(基于引用[1]的原理),并提供一个完整的代码示例。这种方法简单易懂,适合小规模数组,但时间复杂度为 $O(n^2)$(其中 $n$ 是数组长度),因为需要对每个元素进行多次比较。之后,我会讨论优化方法。 #### 基本方法:遍历比较法 该方法的核心思路是遍历原数组,并维护一个新数组(或原数组的一部分)来存储唯一元素。具体步骤如下: 1. **初始化新数组**:创建一个新的数组来存储后的元素。 2. **遍历原数组**:对原数组中的每个元素,检查其是否已存在于新数组中。 3. **添加唯一元素**:如果新数组中不存在该元素,则将其添加到新数组中。 4. **返回结果**:新数组即为后的数组。 这种方法简单,但效率较低,因为对每个元素都需要扫描新数组进行查找,平均时间复杂度为 $O(n^2)$。 #### C语言代码实现 以下是一个完整的C语言程序,实现了上述方法。程序支持动态输入数组大小和元素,并在屏幕上输出后的结果。 ```c #include <stdio.h> #include <stdlib.h> // 函数实现数组 int* removeDuplicates(int arr[], int size, int* newSize) { if (size <= 0) { *newSize = 0; return NULL; // 处理空数组 } int* result = (int*)malloc(size * sizeof(int)); // 分配新数组空间 if (result == NULL) { printf("内存分配失败!\n"); exit(1); } int count = 0; // 新数组的元素计数(初始为0) for (int i = 0; i < size; i++) { // 遍历原数组 int isDuplicate = 0; // 标记是否为复元素,0表示不复 for (int j = 0; j < count; j++) { // 检查新数组中是否已存在该元素 if (arr[i] == result[j]) { isDuplicate = 1; // 标记为复 break; } } if (!isDuplicate) { // 如果未复,添加到新数组 result[count] = arr[i]; count++; } } *newSize = count; // 设置新数组的实际大小 return result; // 返回新数组指针 } int main() { int size; printf("输入数组大小: "); scanf("%d", &size); int* arr = (int*)malloc(size * sizeof(int)); if (arr == NULL) { printf("内存分配失败!\n"); return 1; } printf("输入数组元素(用空格分隔): "); for (int i = 0; i < size; i++) { scanf("%d", &arr[i]); } int newSize; // 存储数组的大小 int* result = removeDuplicates(arr, size, &newSize); // 调用函数 printf("后的数组: "); for (int i = 0; i < newSize; i++) { printf("%d ", result[i]); } printf("\n"); // 释放动态分配的内存 free(arr); free(result); return 0; } ``` #### 代码解释 - **removeDuplicates 函数**:该函数接收原数组数组大小和一个指针变量(用于返回新数组大小)。它使用嵌套循环:外层循环遍历原数组,内层循环检查新数组中是否已存在当前元素。如果不复,则添加元素。 - **时间复杂度**:由于嵌套循环,最坏情况为 $O(n^2)$。这在数组元素较少时高效,但大规模数组时性能较差。 - **空间复杂度**:为 $O(n)$,因为新数组最多存储原数组的所有元素。 - **使用示例**:用户在 `main` 函数中输入数组大小和元素,程序输出结果。例如,输入 `[1, 2, 2, 3, 4, 4]`,输出 `[1, 2, 3, 4]`。 #### 优化方法 基本方法简单但效率低。对于大规模数组,推荐优化方法: - **排序后**:先排序数组(使用快速排序或归并排序,时间复杂度为 $O(n \log n)$),然后遍历一次移除相邻复元素(时间复杂度为 $O(n)$)。整体复杂度为 $O(n \log n)$。 - **使用哈希表**:创建哈希表存储元素,遍历数组时检查哈希表,避免嵌套循环。复杂度可降至 $O(n)$,但需要额外空间。 - **双指针法**:如果允许修改原数组,使用双指针原地操作:一个指针遍历数组,另一个指针指向唯一元素的位置。复杂度为 $O(n)$,但需先排序。 这些优化方法在性能上显著优于基本方法,尤其适用于大型数据集[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值