Bootstrap

C去重排序3种方法

C语言实现去重 升序排序输出

在这里插入图片描述

1.前几天一哥们面试题,让从1-1000序号中随机选取7个数作为年终颁奖名额,其中一个人不能重复领奖,,,,这就是明显的去重操作 ,,,当时用Java写的Set集合

在这里插入图片描述

小明公司有1000人,今年年会举行抽奖活动,一次抽出三等奖4名,二等奖2名,一等奖1名
https://blog.csdn.net/qq_45896330/article/details/122971352

2.最近几天又有小伙伴搞C语言问一位数组怎么去重

在这里插入图片描述

排序去重思路

首先对这个数据进行排序(本人比较喜欢冒泡排序),然后比较相邻的是否存在重复
如果存在重复3种方案
方案一:(巧妙法)在输出的时候进行判断相同的元素只输出一次
方案二:引入新的数组,排序后的数组比较相邻的元素,如果相同只把一个放入新数组
方案三:在原来数组上把重复的给删除
其实还有很多方法(比如桶排序的思想,把相同的数放在同一桶里面,最后输出的时候直接判断桶中书否有数,有的话直接输出一次下标,根据题意如果数组中数的范围比较小可以采用,但是书比较大的时候就比较浪费空间了,毕竟数组申请连续的内存空间是很浪费资源的),相对来说比较麻烦第一种方案比较好一点

如果是只是去重的话,可以采用类似方法一的技巧

2.1方法一(巧妙法)在输出的时候进行判断相同的元素只输出一次

先排序,再去重

//数组去重后   升序输出 
#include<stdio.h>
void Sort(int a[],int n); 
int main(){
	int n,i,j;
	int a[10];
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	Sort(a,n);
	
	printf("%d",a[0]);
	for(int j = 0; j < n-1; j++) {   
		if(a[j]!=a[j+1]){            //如果后边的不等于前面的就把后边的数输出 
			printf(" %d",a[j+1]);
		}
	}

}
void Sort(int a[],int n){   //冒泡排序(升序)每次把最大的元素放在后边 
	for(int i=0;i<n-1;i++){
		int flag=0;   //冒泡排序的截止条件(如果一个数组本来就是有序的就直接终止排序) 
		for(int j=0;j<n-i-1;j++){  //每次排序后边的都拍好一个元素,下次就少比较一次 
			if(a[j]>a[j+1]){
				flag=1;
				int temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			}
		}
		if(flag==0){
			break;  //提前终止 
		}
	}
}

输入
10
1 2 3 4 5 4 3 2 9 1

输出:
1 2 3 4 5 9
在这里插入图片描述

2.2方案二:引入新的数组,排序后的数组比较相邻的元素,如果相同只把一个放入新数组

先排序 再去重

//数组去重后   升序输出 
#include<stdio.h>
void Sort(int a[],int n); 
int main(){
	int n,i,j;
	int a[10];
	int arr[10];
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	Sort(a,n);
	
	int l = 0; //记录新数组的下标 
	//printf("%d",a[0]);
	arr[0]=a[0];
	for(int j = 0; j < n-1; j++) {   
		if(a[j]!=a[j+1]){            //如果后边的不等于前面的就把后边的数输出 
			//printf(" %d",a[j+1]);
			arr[++l]=a[j+1];
		}
	}
	
	printf("%d",arr[0]);
	for(int i=1;i<=l;i++){    //此时的l 表示的下标不是长度  此时可以为等号 
		printf(" %d",arr[i]);
	}

}
void Sort(int a[],int n){   //冒泡排序(升序)每次把最大的元素放在后边 
	for(int i=0;i<n-1;i++){
		int flag=0;   //冒泡排序的截止条件(如果一个数组本来就是有序的就直接终止排序) 
		for(int j=0;j<n-i-1;j++){  //每次排序后边的都拍好一个元素,下次就少比较一次 
			if(a[j]>a[j+1]){
				flag=1;
				int temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			}
		}
		if(flag==0){
			break;  //提前终止 
		}
	}
}


测试输入:
10
1 2 1 0 5 3 2 0 7 9

结果输出:
0 1 2 3 5 7 9
在这里插入图片描述

2.3方案三:在原来数组上把重复的给删除

这个方法是最麻烦的方法,数组是以下标索引的,前边删除一个元素后边的元素都需要往前移动一位
先排序,再去重

//数组去重后   升序输出 
#include<stdio.h>
void Sort(int a[],int n); 
int main(){
	int n,i,j;
	int a[10];
	int arr[10];
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	Sort(a,n);
	
	for(i = 0; i < n-1; i++) {   
		if(a[i]==a[i+1]){            //后一个元素是否等于前一个元素,是的话把后边的元素覆盖掉 
			for(j=i+1;j<n-1;j++){
				int temp = a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			} 
			n--;   // 覆盖掉一个元素,数组总长度-1 
			i--;   //重新比较这个位置上的元素和覆盖的元素  1 1 1 3(当i=0时a[0]=a[1]会把a[1]给覆盖掉,1 1 3覆盖的元素还是1还需要比较,此时要退回来再比较覆盖后的元素) 
		}
	}
	
	printf("%d",a[0]);
	for(int i=1;i<n;i++){
		printf(" %d",a[i]);
	}
	
	
}
void Sort(int a[],int n){   //冒泡排序(升序)每次把最大的元素放在后边 
	for(int i=0;i<n-1;i++){
		int flag=0;   //冒泡排序的截止条件(如果一个数组本来就是有序的就直接终止排序) 
		for(int j=0;j<n-i-1;j++){  //每次排序后边的都拍好一个元素,下次就少比较一次 
			if(a[j]>a[j+1]){
				flag=1;
				int temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			}
		}
		if(flag==0){
			break;  //提前终止 
		}
	}
}

测试输入:
10
0 0 0 3 5 0 1 1 1 0

结果输出:
0 1 3 5
在这里插入图片描述

2.4只去重 不排序

(重复的保留后边的)

  1. 直接双重循环比较第一个元素与后边所有元素是否重复,若重复直接跳过输出,不重复输出
  2. 然后比较第二个元素与后边所有元素是否重复,若重复直接跳过,不重复输出
  3. 最终的话,会输出每个重复元素的最后一个元素
//数组去重后 
#include<stdio.h>

int main(){
	int n,i,j;
	int a[10];
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}

	//不排序直接去重 
	for(int i = 0; i < n; i++) {
		bool flag = false;
		for(int j = i + 1; j < n; j++) {
			if (a[i] == a[j]) {
				flag = true;      //比较前边的元素和后边的元素是否相同,,,相同的话跳过不输出,,,(相当于重复的输出最后一个) 
				break; //只要发现有一个重复的就没必要继续比下去了,直接终止本次循环 
			}	
		}
		if(!flag) {
			printf("%d ", a[i]);
		} 
	}
}

测试输入:
10
1 2 1 1 0 5 0 6 3 4

结果输出:
2 1 5 0 6 3 4在这里插入图片描述这种去重的思想和插入排序差不多,时间复杂度都是O(n2),插入的话是每次比较后找到自己合适的位置放下,这个是从前往后找与自己相同的元素,找到就跳过输出下一位,找不到就输出
在这里插入图片描述

在这里插入图片描述

;