第B练——数组及元素操作

第B练——数组及元素操作

  1. 数组及元素操作

1.1. 排序三数:Sort3Num.cpp(本题10分) 【题目描述】 输入3个数a, b, c,利用指针方法,按从小到大的顺序输出。

【程序分析】
利用指针方法。
【输入】
输入文件Sort3Num.in有1行,包含3个int整数,即输入的变量a, b, c。
【输出】
输出文件Sort3Num.out有1行,包含3个int整数(空格隔开),即输出的3个整数。
【输入输出样例1】
Sort3Num.in Sort3Num.out
8 5 7 5 7 8
【输入输出样例2】
Sort3Num.in Sort3Num.out
4 5 3 3 4 5

#include <stdio.h>

/*功能: 通过指针交换2个数*/
void swap(int *p1, int *p2){
	int p; 
	//******************************************
	p = *p1;
	*p1 = *p2;
	*p2 = p; 
	//==========================================
}

int main(){ 
	int a, b, c; //a,b,c-三个整型变量
	int *pointer1, *pointer2, *pointer3; //三个整型指针
	printf("请输入3个整数(a b c),空格隔开:");

	FILE *fp;
	if((fp=fopen("Sort3Num.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("Sort3Num.in", "r", stdin);
		freopen("Sort3Num.out", "w", stdout);
	}

	scanf("%d%d%d", &a, &b, &c); //输入三个整数
	//*******************************************
	
	pointer1 = &a; 
	pointer2 = &b; 
	pointer3 = &c; 
	
	if(a>b){
		swap(pointer1, pointer2); 
	}
	
	if(a>c){
		swap(pointer1, pointer3); 
	}
	
	if(b>c){
		swap(pointer2, pointer3); 
	}

	//============================================
	printf("%d %d %d", a, b, c); //输出交换后(从小到大有序)的3个整数 
	
	return 0;
}

1.2. 最大最小数组元素:ArrayNum.cpp(本题15分) 【题目描述】 输入数组元素个数n以及n个整型数组元素,将值最大的元素与第一个元素交换,值最小的元素与最后一个元素交换,并输出最终的数组。

【程序分析】
首先遍历数组,保留最大最小元素的下标。之后进行相应操作。
注意:值最小元素在头、值最大元素在尾时的特殊情况处理!
【输入】
输入文件ArrayNum.in有2行,第1行是一个整数n;第2行有n个整数,整数之间用空格隔开。
【输出】
输出文件ArrayNum.out有1行,包含n个整数,整数之间用1个空格隔开。
【输入输出样例1】
ArrayNum.in ArrayNum.out
10
23 21 5 98 19 12 6 10 8 61 98 21 61 23 19 12 6 10 8 5
【输入输出样例2】
ArrayNum.in ArrayNum.out
12
4 4 4 4 4 5 5 6 6 6 6 6 6 4 4 4 4 5 5 6 6 6 6 4
【数据限制】
1≤n≤1000。

#include <stdio.h>

const int N0=1000;

/*功能:值最大的元素与第一个元素交换,值最小的元素与最后一个元素交换*/
void max_min(int array[10], int n){
	int *max, *min, *p, temp; //max-指向最大数组元素的指针; min-指向最小数组元素的指针; p-遍历数组的指针; temp-元素交换的临时变量
	//*********************************************
	//(1)初始化最大最小元素的指针
	max = array; 
	min = array;

	//(2)遍历数组,寻找最大最小元素
	for(p=array+1; p<array+n; p++){
		if(*p > *max){
			max = p; 
		}
		if(*p < *min){
			min = p;
		}
	}
	
	//(3)值最大的元素与第一个元素交换
	temp = *max; 
	*max = array[0];
	array[0] = temp;

	//(4)值最小的元素与最后一个元素交(注意处理: 值最小元素在头、值最大元素在尾的情况)
	if(min == array){
		min = max;
	}

	temp = *min; 
	*min = array[n-1];
	array[n-1] = temp;
	//=============================================
} 

int main(){
	int number[N0], n, i;		//a-整型数组; n-数组元素个数; i-循环变量
	
	printf("请输入整数个数n及n个整数), 空格隔开:");
	
	FILE *fp;
	if((fp=fopen("ArrayNum.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("ArrayNum.in", "r", stdin);
		freopen("ArrayNum.out", "w", stdout);
	}
	
	scanf("%d", &n);		//输入数组元素个数
	for(i=0; i<n; i++){	//输入数组元素
		scanf("%d", &number[i]);
	}
	//*********************************************
	
	max_min(number, n); //调用函数max_min(...)实现最大最小元素与首尾元素的交换
	
	//=============================================
	for(i=0; i<n; i++){	//通过指针p遍历数组,并输入数组元素
		printf("%d ", number[i]);
	}
	
	return 0;
} 


1.3. 选择排序:SelectSort.cpp(本题15分) 【题目描述】 输入数组元素个数n以及n个整型数组元素,使用选择排序算法对n个整数进行排序,使之从小到大有序。

【程序分析】
利用选择法,将第i个元素与其后的n-i个元素进行比较,选择最小的元素(可能多个,只选一个)与第i个元素进行交换。依次类推,进行循环,直到所有元素从小到大有序。
【输入】
输入文件SelectSort.in有2行,第1行是一个整数n;第2行有n个整数,整数之间用空格隔开。
【输出】
输出文件SelectSort.out有1行,包含n个从小到大有序的int整数,即有序数组的元素值,整数之间用1个空格隔开。
【输入输出样例1】
SelectSort.in SelectSort.out
10
23 28 5 98 5 12 6 10 28 61 5 5 6 10 12 23 28 28 61 98
【输入输出样例2】
SelectSort.in SelectSort.out
20
23 21 5 76 19 12 16 12 8 61 89 69 56 34 96 37 67 87 5 32 5 5 8 12 12 16 19 21 23 32 34 37 56 61 67 69 76 87 89 96
【数据限制】
1≤n≤1000。

#include <stdio.h>
#define N 1000

int main(){
	int a[N], n; //a-整型数组; n-数组元素个数
	int i, j, min, temp;//i,j-循环变量; min-一趟选择排序过程中找到的最小元素的下标; temp-元素交换临时变量
	
	printf("请输入整数个数n及n个整数), 空格隔开:");
	FILE *fp;
	if((fp=fopen("SelectSort.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("SelectSort.in", "r", stdin);
		freopen("SelectSort.out", "w", stdout);
	}	
	
	scanf("%d", &n);		//输入数组元素个数
	
	for(i=0; i<n; i++){	//输入数组元素
		scanf("%d", &a[i]);
	}
	//****************************************
	/*(1)使用选择法排序数组*/ 
	for(i=0; i<n; i++){
		//(a)初始化最小元素的下标
		min = i; 
		
		//(b)遍历数组,获得最小元素的下标
		for(j=i+1; j<n; j++){ 
			if(a[min] > a[j]){
				min = j; 
			}
		}
		
		//(c)将最小元素与首元素交换
		temp=a[i]; 
		a[i]=a[min]; 
		a[min]=temp; 
	}
	
	/*(2)输出最终的数组数据*/ 
	for(i=0; i<n; i++){
		printf("%d ", a[i]);
	}
	//============================================
	
	return 0;
}

1.4. 数组元素插入:InsertNumber.cpp(本题20分) 【题目描述】 有一个已经从小到大排序好的int型数组。现要求输入一个整数number(int型)并将其插入数组,要求插入number后的数组仍有序。

【程序分析】
首先判断此数number与数组首尾元素的关系,尤其是此数与最后一个元素的大小关系,若此数number大于最后一个数,则直接插入在数组末端,无需移动原来的数组元素;否则,此数number将插入在数组的中间,插入number后此元素之后的元素须依次往后移一个位置。
注意:给定的数组的长度N,已有数组个数N-1。插入数据存放于数组最后一个位置,即数组下标N-1。
【输入】
输入文件InsertNumber.in有1行,包含1个int整数,即输入的变量number。
【输出】
输出文件InsertNumber.out有1行,包含若干个从小到大有序的int整数,即原数组基础上插入number后仍有序的数组,整数之间用1个空格隔开。
【输入输出样例1】
InsertNumber.in InsertNumber.out
-8 -8 1 4 6 9 13 16 19 28 32 43 55
【输入输出样例2】
InsertNumber.in InsertNumber.out
10 1 4 6 9 10 13 16 19 28 32 43 55

#include <stdio.h>
#define N 12
int main(){
	int a[N]={1, 4, 6, 9, 13, 16, 19, 28, 32, 43, 55}; //当前共11个数组元素
	int number, i; //number-待输入的整数; i-循环控制变量
	
	printf("请输入待插入的整数(number):"); 
	
	FILE *fp;
	if((fp=fopen("InsertNumber.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("InsertNumber.in", "r", stdin);
		freopen("InsertNumber.out", "w", stdout);
	}
	
	scanf("%d", &number);	//输入数组元素个数
	//******************************************
	if(number > a[N-2]){//若插入元素比最好一个元素大,则直接插入在最后
		a[N-1] = number;
	}else{//若插入元素number插入在数组‘内部’,则...
		//从数组右端开始遍历、并将数组往后移动,直到碰到找到不比number大的元素
		for(i=N-2; i>=0; i--){
			if(a[i] > number){
				a[i+1] = a[i];
			}else{
				break;
			}
		}

		//待插入元素number插入在(i-1)位置上
		a[i+1] = number;
	}

	//============================================
	for(i=0; i<N; i++){//输出数组数据
		printf("%d ", a[i]);
	}

	return 0;
}

1.5. 元素移动:ElementMove.cpp(本题20分) 【题目描述】 输入数组元素的个数n及n个整型(int)数组元素数据,以及移动的步长m,使数组的前面各数顺序向后移m个位置,最后m个数变成最前面的m个数,即数组元素自左向右循环转动m个位置。

【程序分析】
程序实现有两种方式,一是:每次自左向右移动1位,循环m次,达到移动m位的效果;二是:计算好移动m位后个元素的对应位置关系,每个元素只进行一次移动。
注意:由于长度为n的数组元素的移动具有周期性,即移动步长为n的整数倍时 数组保持原样(不变),等价于不移动,因此,移动步长m可以取值为对n求余数的结果,即m%n。
【输入】
输入文件ElementMove.in有3行,第一行包含1个int型整数,表示数组元素的个数n,即变量n。第二行包含n个空格隔开的整数,即数组number各元素的值。第三行包含1个int型整数,表示数组元素的循环移动的步长,即变量m。
【输出】
输出文件ElementMove.out有1行,包含n个空格隔开的整数,即原数组元素自左向右循环移动m次后的数组数据。
【输入输出样例1】
ElementMove.in ElementMove.out
10
23 21 5 98 19 12 6 10 8 61
13 10 8 61 23 21 5 98 19 12 6
【输入输出样例2】
ElementMove.in ElementMove.out
12
11 6 15 8 21 33 8 35 48 39 17 42
241 42 11 6 15 8 21 33 8 35 48 39 17
【数据限制】
n≥1,m≥0。

#include <stdio.h>

#define N 1000

void move(int array[N], int n, int m){ 
	int i, temp; //i-数组循环变量; temp-临时变量 
	//************************************************
	/*方法(一):递归调用*/
	/*(1)若移动步长m>0, 则所有元素自左向右移动1位*/
	if(m > 0){
		//(1.1)保留数组元素的最后一个元素
		temp = array[n-1]; //保存最后一个元素
		
		//(1.2)将最后一个元素之前的所有n-1个元素向右移动一个位置
		for(i=n-1; i>0; i--){
			array[i] = array[i-1]; 
		}
		array[i] = temp; //array[0] = temp;//数组首元素=原数组最后一个元素 
		
		//(1.3)更改移动步长,递归,进行下一轮调用
		move(array, n, --m); 
	}
	
	/*方法(二):循环移动*/
	/*
	if(m > 0){
		for(int k=0; k<m; k++){//m次循环移动
			//(1.1)保留数组元素的最后一个元素
			temp = array[n-1]; //保存最后一个元素
			
			//(1.2)将最后一个元素之前的所有n-1个元素向右移动一个位置
			for(i=n-1; i>0; i--){
				array[i] = array[i-1]; 
			}
			array[i] = temp; //array[0] = temp;//数组首元素=原数组最后一个元素 
		}
	}
	*/
	//================================================
}

int main() {
	int number[N], n, m, i; //n-数据个数; i-循环变量
	
	printf("请输入数据个数n和n个数据,以及移动的距离m:"); 
	FILE *fp;
	if((fp=fopen("ElementMove.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("ElementMove.in", "r", stdin);
		freopen("ElementMove.out", "w", stdout);
	}
	
	scanf("%d", &n);		//输入数组元素个数
	
	for(i=0; i<n; i++){	//输入数组元素
		scanf("%d", &number[i]);
	}
	
	scanf("%d", &m);		//数据移动位数
	//************************************************
	
	/*方法(1): */
	//m = m%n; //去除可能无效的周期移动(不管m是否大于n!!)
	//move(number, n, m); //调用函数move(...)将长度为n的数组number的
	
	/*方法(2): */
	move(number, n, m%n); //调用函数move(...)将长度为n的数组number的
	
	//================================================
	for(i=0; i<n; i++){
		printf("%d ", number[i]);
	}
	
	return 0;
} 

1.6. 数字抽出:DropNumber.cpp(本题20分) 【题目描述】 有n(程序输入)个人围成一圈,顺序编号(从1开始编号,直到n)。从第一个人开始报数(从1到3报数),凡是报到3的人退出圈子,问第m(程序输入)个退出的人的编号是多少?若第m次‘退出’之前所有人已经退出,则输出最后一个退出的人的编号。

【程序分析】
本题要求学生熟练掌握循环控制。对于本题的实现:
 n个人员的编号存储于整型数组中,并由程序通过循环进行初始化。
 人员报数和退出的实现,采用数组元素遍历的方式。
 遍历数组元素时,程序可将退出人员的编号置为特殊标识(如“-1”),后续遍历时略过这些特殊元素。
 一旦遍历到数组尾元素,则将游标移动到数组首元素,从而形成虚拟的圆圈遍历控制。
 程序进行循环,直到找到满足条件的人员、或者所有人员都已经退出。
【输入】
输入文件DropNumber.in有1行,包含2个int类型的整数(空格隔开),即初始时刻的总人数(n)和想要获得的第m个退出的人的序号(m)。
【输出】
输出文件DropNumber.out有1行,包含1个int类型的整数,即第m个退出的人的编号。
【输入输出样例1】
DropNumber.in DropNumber.out
20 6 18
【输入输出样例2】
DropNumber.in DropNumber.out
20 18 2
【输入输出样例3】
DropNumber.in DropNumber.out
20 118 20
【数据限制】
1≤n≤5000,m≥1。

#include <stdio.h>
#define nmax 5000

int main() { 
	int n, num[nmax], m, id; //n-总人数; num-人编号; m-待获得的退出人员的序号; id-第m次退出人员的编号id
	int i, k, count;//i-循环控制变量; k-人员报号数; count-已退出人员计数
	
	printf("请输入总人数n和序号m:"); 
	FILE *fp;
	if((fp=fopen("DropNumber.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("DropNumber.in", "r", stdin);
		freopen("DropNumber.out", "w", stdout);
	}
	
	scanf("%d%d", &n, &m);		//输入总人数n 和 退出人员的序号m
	
	//********************************************************************
	//(1)初始化人员的编号
	for(i=0; i<n; i++){
		num[i] = i + 1;
	}

	//(2)若m大于n, 则求最后一个(第n个)退出的人,...
	if( m>n ){ 
		m = n;
	}
	
	//(3)模拟数 的过程,循环遍历数组元素,直到找到第m个退出的人
	k = 0; //人员的叫号
	count = 0; //退出的人员的计数
	for(i=0;  ;i++){
		//(3.1)若此元素有效(还没退出!),则报数 
		if(num[i%n] != -1){
			//A.人员报数+1
			k++; 
			
			//B.若此人员的报数是3的倍数,则累加退出人员的数目 & 并将元素值置为-1(表示此人退出)
			if(k%3 == 0){ //若报数是3的倍数, 则将此元素置为-1
				//(B.1)退出人员的数目+1
				count++;
				//printf("报数=%d, 下标=%d, 编号=%d\n", k, i, num[i]);
				
				//(B.2)若此次(count)退出的人员num[i] ->即为要找的人员(m==count)或所有人员都已经退出(n==count), 则找到&退出循环
				if( count >= m ){ //if((count == m) || (count == n)){ //找到第m个退出的人 
					id = num[i%n]; 

					break;
				}

				//(B.3)将此退出人员的编号置为-1
				num[i%n] = -1;
			}
		}
	}
	
	//(4)输出第m次(当m>n时,输出第n个退出的人)退出的人员的编号
	printf("%d", id); // printf("报数=%d, ID=%d \n", k, id);
	//======================================================================
	return 0;
}

#include <stdio.h>
#define nmax 5000

int main() { 
	int n, num[nmax], m, id; //n-总人数; num-人编号; m-待获得的退出人员的序号; id-第m次退出人员的编号id
	int i, k, count;//i-循环控制变量; k-人员报号数; count-已退出人员计数
	
	printf("请输入总人数n和序号m:"); 
	FILE *fp;
	if((fp=fopen("DropNumber.in", "r")) != NULL ){
		fclose(fp);  //存在的话,要先把之前打开的文件关掉
		
		freopen("DropNumber.in", "r", stdin);
		freopen("DropNumber.out", "w", stdout);
	}
	
	scanf("%d%d", &n, &m);		//输入总人数n 和 退出人员的序号m
	
	//********************************************************************
	//(1)初始化人员的编号
	for(i=0; i<n; i++){
		num[i] = i+1;
	}
	
	//(2)循环遍历数组元素,直到:1)所有元素(人)都已经退出,或者 2)已经找到第m个退出的人
	i=0; //i-数组的遍历游标
	count = 0; //退出的人员的计数
	k = 0; //人员的叫号
	while(count < n){
		//(2.1)若此元素有效(还没退出!)
		if(num[i] != -1){
			//A.人员报数+1
			k++; 
			
			//B.若此人员的报数是3的倍数,则累加退出人员的数目 & 并将元素值置为-1(表示此人退出)
			if(k%3 == 0){ //若报数是3的倍数, 则将此元素置为-1
				//printf("报数=%d, 下标=%d, 编号=%d\n", k, i, num[i]);
				
				//(B.1)退出人员的数目+1
				count++; 
				
				//(B.2)若此次(count)退出的人员num[i] ->即为要找的人员(m==count)或所有人员都已经退出(n==count), 则找到&退出循环
				if((count == m) || (count == n)){
					id = num[i]; 

					break;
				}

				//(B.3)将此退出人员的编号置为-1
				num[i] = -1;
			}
		}
		
		//(2.2)数组的遍历游标i往后移动【若达到数组最后一个,则移动到首个->形成圆圈】
		i++; //数组的下一个元素
		if(i == n){
			i = 0; //将数组的遍历游标移动到首个元素
		}
	}

	//======================================================================
	//输出第m次(当m>n时,输出第n个退出的人)退出的人员的编号
	printf("%d", id); // printf("报数=%d, ID=%d \n", k, id);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值