超星高级语言程序设计实验作业 (实验04 数组及其在程序设计中的应用)(一)

超星高级语言程序设计实验作业

实验04 数组及其在程序设计中的应用(一)

注:以下内容仅供交流,代码都是本人自己写的,还请同学们先自己编写再进行交流。

1.括号匹配

题目描述:编写程序,从终端读入以‘@’为结束符的字符序列,检查该字符序列中的 ( 与 )、 [ 与 ] 、{ 与 } 是否匹配(个数相等且位置不相交)。
输入:包含一串以‘@’为结束符的字符串,其间可能包含空白或其它非括号字符。
输出:如果字符串中三类括号匹配,则输出YES;否则输出NO。
样例1:
输入:{a,a}b{c[cc]c} {a(bb[cc]dd)a}@
输出:YES
样例2:
输入:{a,a}b{c[cc]c] {a(bb[cc]dd)a}@
输出:NO

#include
#define size 100
int top=0;
char a[100];
bool push(char x) {
	if (top>size-1)return false;
	else{
		a[top] = x;
		top++;
		return true;
	}
}
	
char pop(void) {
	if (top == 0) return '\0';
	else {
		top--; 
		return a[top];
	}
}
int check(char x, char y) {
	if (x == '\0' || x == '@') { printf("NO"); return 0; }
	else if (x != y) { printf("NO"); return 0; }
	else return 1;
}
int main() {
	char ch,out;
	int i=1;
	push('@');
	ch = getchar();
	while (ch != '@') {
		switch (ch){
			case'[':
			case'(':
			case'{':push(ch); break;
			case']':out = pop();i= check(out, '['); break;
			case'}':out = pop();i= check(out, '{'); break;
			case')':out = pop();i= check(out, '('); break;
			default:break;
		}
		ch = getchar();
		if (i == 0) break;
	}
	out = pop();
	if (i == 1)
	{
		if (out == '@'){
			printf("YES");
		}
		else{
			printf("NO");
		}
	}
	return 0;
}

比较简单的照着课本上的写就行。

2.n倍数关系

题目描述:给定若干互不相同正整数(<10000)和n(n<5),计算这些正整数里面有多少数对满足:其中一个是另一个的n倍。例如:1 4 3 2 9 7 18 22,n=3时得到的答案是2;因为3是1的3倍,9是3的3倍。

输入:输入第一行给出正整数n的值,接下来包括多组测试数据。每组数据最多100个整数占用一行,以数字0结束。最后一行只包括-1,表示输入数据结束。

输出:对每组输入数据,输出一行,给出有多少数对满足其中一个是另一个n倍。(注:最后一行末尾无换行符等多余字符。)

样例:
输入:
2
1 4 3 2 9 7 18 22 0
2 4 8 10 0
7 5 11 13 1 3 0
-1
输出:
3
2
0

#include
int a[100][100], b[100];
//以下是输入部分
int input() {
	char ch = 0;
	int size, i, k = 0;
	for (i = 0;; i++) {
		ch = 0;
		for (k = 0; ch != '\n'; k++) {
			scanf_s("%d", &a[i][k]);
			ch = getchar();
		}
		//当读入最后一个字符后,k比输入的数字(不包括最后的0)个数多1要减去1
		k = k - 1;
		if (a[i][k] == -1)break;
		b[i] = k;       //用数组b储存第i行数字的个数
	}
	return i;    //返回行数
}
//以下是判断部分
void judge(int n, int size) {
	int i, j, k;
	int sum;
	//当n不等于1时正常判断
	if (n != 1) {
		for (i = 0; i < size; i++) {
			sum = 0;
			for (j = 0; j < b[i]; j++) {
				for (k = 0; k < b[i]; k++) {
					if (a[i][j] * n == a[i][k]) sum = sum + 1;
				}
			}
			b[i] = sum;
		}
	}
//当n等于1时,判断相等但同时要从当前判断的数的后一个开始判断,避免记数它本身
	else{
		for ( i = 0; i < size; i++){
			sum = 0;
			for ( j = 0; j < b[i]; j++){
				for (k = j+1; k < b[i]; k++){
					if (a[i][j] == a[i][k]) sum++;
				}
			}
			b[i] = sum;    //用b来储存第i行中满足条件的对数
		}
	}
}
//主函数,负责调用及输出
int main() {
	int n, size;
	scanf_s("%d", &n);
	size = input();
	judge(n, size);
	for (size_t i = 0; i < size; i++) {
		printf("%d", b[i]);
		if (i != size - 1) printf("\n");
	}
	return 0;
}

3. 数组排序

题目描述: 编写函数,分别采用“主元选择排序”、“冒泡排序”和“逐步增加递增子序列”排序方法对给定数组进行排序。综合运用调试方法,观察不同排序方法在排序过程中数组元素值的变化情况,如观察递增排序如下序列{9、8、7、6、5、4、3、2、1、0},{0、1、2、3、4、5、6、7、8、9、0}和{2、9、4、7、6、5、8、3、0、1}时,数组中元素比较次数、移动或交换次数。

说明:
(1)对于“主元选择排序”和“冒泡排序”,执行完3个赋值操作,计为1次交换。
(2)对于“逐步增加递增子序列”排序,如果在某轮比较中元素本身的位置没有变化,则本轮移动次数为0。
(3)因本题目的是观察输出数据,深入理解排序算法;所以样例点和实测点一致。

输入:包含10个整数的待排序数组。
输出:在一行内依次输出,递增排序时,主元排序比较次数 和 移动/交换次数、冒泡排序比较次数 和 移动/交换次数和递增子序列排序比较次数 和 移动/交换次数,相邻数字之间以一个西文空格间隔。

样例1:
输入:
9 8 7 6 5 4 3 2 1 0
输出:
45 9 90 45 54 54

样例2:
输入:
0 1 2 3 4 5 6 7 8 9
输出:
45 9 9 0 9 0

样例3:
输入:
2 2 3 3 5 5 4 4 6 6
输出:
45 9 27 4 13 6

样例4:
输入:
1 0 3 2 5 4 7 6 9 8
输出:
45 9 18 5 14 10

样例5:
输入:
1 2 3 4 5 5 4 3 2 1
输出:
45 9 81 20 29 24

#include
#include  						//数组需要复制,所以需要包含头文件string.h
int a[10];          						//声明数组
int y1=0, y2=0, y3=0;						//函数只能返回一个值,所以需要全局变量来存储比较次数
//以下是主元排序部分
int zhuyuan(){
	int sum=0;
	int b[10],i,j,k,r;
	memcpy(b,a,sizeof(a));     				//调用函数将a数组复制给b数组
	for ( i = 0; i < 9; i++){
		j = i;
		for ( k = i+1; k < 10; k++){
		
			y1++;							//记录比较的次数		

			if (b[k] < b[j]) j = k;
		}
		r = b[i]; b[i] = b[j]; b[j] = r; 
		sum++;    							//记录移动次数
	}
	return sum;
}
//以下是冒泡排序部分
int maopao() {
	int sum=0;
	int b[10], i,r,flag=1;
	memcpy(b, a, sizeof(a));
	while (flag){
		flag = 0;
		for (i = 0; i < 9; i++){
			y2++;						//记录比较次数
			if (b[i]>b[i+1]){
				r = b[i]; b[i] = b[i + 1]; b[i + 1] = r; 
				sum++;					//记录移动次数
				flag = 1;
			}
		}
	}
	return sum;
}
//以下是逐步增加递增子序列法
int zhubu() {
	int sum=0;
	int b[10], i, j, k, r,flag;
	memcpy(b, a, sizeof(a));
	for (i = 1; i < 10; i++) {
		flag = 0;
		j = i - 1;
		while ((b[j] > b[i]) && (j >= 0)) {
			j = j - 1; 
			flag = 1; 				//用于判断是否有移动
			y3++; 					//记录比较的次数中进入while部分
		}
		r = b[i];
		for (k = i - 1; k >= j + 1; k--) {
			b[k + 1] = b[k];
			if (flag) sum++;		//记录移动次数中部分移动
		}
		if (flag) sum++; 			//移动次数加上未在循环中的部分
		b[j + 1] = r; 
	}
	y3 = y3 + 9;					//比较中有9次条件不成立未进入循环
	return sum;
}
int main() {
	int x1,x2,x3;
	int i;
	for ( i = 0; i < 10; i++){
		scanf_s("%d", &a[i]);
	}
	x1 = zhuyuan();
	x2 = maopao();
	x3 = zhubu();
	printf("%d %d %d %d %d %d", y1, x1, y2, x2, y3, x3);
	return 0;
}

这道题,有亿点复杂,函数部分照抄课本,但是计数部分需要自己深入理解排序的原理,尤其是逐步增加递增子序列的计数中,那九次无法直接计入进去只能在最后加上,希望有大佬指点这部分的算法优化,有想法的同学也可以评论交流。
对了,还有因为三个程序都要用到数组排序但是排序之前又需要数组一样所以用了string.h中的memcpy函数将a复制给b,大家还有更好的方法吗,欢迎指教。

4.删除重复元素

题目描述:编写函数,不使用其他辅助数组,把整型数组中重复元素删得只剩一个;所有未被删除元素都保留最先顺序移动到数组前面。
输入:第一行输入数组长度n(≤100),第二行依次从键盘随机输入n个整数作为数组元素值。
输出:已删除重复元素的数组,各元素间以一个西文空格间隔,最后一个元素后无字符。
样例1:
输入:
10
1 1 2 3 3 3 2 1 2 4
输出:
1 2 3 4
样例2:
输入:
10
1 0 2 2 2 2 2 2 2 2
输出:
1 0 2

#include
int a[100];
//以下函数是检测重复元素并删除的部分
int judge(int n) {
	int i,k,r,sum=n;
	for ( i = 0; i < n; i++){
		for (k = i+1; k < sum; k++){
			if (a[i]==a[k]){
				sum--; 
				for ( r = k; r < sum; r++){
					a[r] = a[r + 1];
				}
				k = i;		//当判断有重复后重新从当前数后开始检测是否有重复
			}
			
		}
	}
	return sum;			//sum用于计数删除后还有多少个元素
}
int main() {
	int n,sum;
	scanf_s("%d", &n);
	int i;
	for ( i = 0; i < n; i++){
		scanf_s("%d", &a[i]);
	}
	sum=judge( n);
	for ( i = 0; i < sum; i++){
		printf("%d", a[i]);
		if (i != sum - 1) printf(" ");
	}
	return 0;
}

题目中

k=i;

部分是为了防止出现三个或以上重复数连续出现导致后判断后k直接自增略过改变后k之后第一个数。

5.转移0元素

题目描述:编写程序,不使用其他辅助数组,把给定整型数组中所有0元素全部移到后面,且所有非0元素的顺序不变。
输入:第一行输入数组长度n(≤100),第二行依次从键盘随机输入n个整数作为数组元素值。
输出:已将所有0元素串到后面的整数数组,各元素间以一个西文空格间隔,最后一个元素后无字符。
样例1:
输入:
10
0 3 1 0 0 0 1 2 3 0
输出:
3 1 1 2 3 0 0 0 0 0
样例2:
输入:
10
0 0 0 0 0 0 1 2 3 4
输出:
1 2 3 4 0 0 0 0 0 0

#include
int a[100];
//判断及删除函数部分
void judge(int n) {
	int i,k,r,sum=n;
	for ( i = 0; i <sum;){
		if (a[i] == 0) {
			a[n] = 0;
			sum--;		//sum用于计数还有多少个数字需要判断
			for (k = i; k <= sum; k++){
				a[k] = a[k + 1];
			}
		}
		else i++;     //如果当前判断位置不为0再判断下一个位置
	}
}
int main() {
	int n;
	scanf_s("%d", &n);
	int i;
	for ( i = 0; i < n; i++){
		scanf_s("%d", &a[i]);
	}
	judge(n);
	for ( i = 0; i < n ; i++){
		printf("%d", a[i]);
		if (i != n - 1)  printf(" ");
	}
	return 0;
}

因为数组默认初值为0,所以取巧直接用后面的数赋给前面的数,从而做到将0后移。

6.循环右移

题目描述:编写程序,不使用其它辅助数组,把一维整型数组中的各个元素循环右移j位。
输入:
第一行输入两个整数,n表示数组长度(0=0);
第二行依次从键盘随机输入n个整数作为数组元素值。
输出:
循环右移后的整数数组,各元素间以一个西文空格间隔,最后一个元素后无字符。
样例1:
输入:
10 2
1 2 3 4 5 6 7 8 9 0
输出:
9 0 1 2 3 4 5 6 7 8
样例2:
输入:
10 23
1 2 3 4 5 6 7 8 9 0
输出:
8 9 0 1 2 3 4 5 6 7

#include
void input(int a[],int n) {
	for (int i = 0; i < n; i++){
		scanf_s("%d", a + i);
	}
}
void change(int a[],int n,int ch) {
	int r;
	int i,k;
	for ( i = 0; i < ch; i++){
		r = *(a + n - 1);
		for ( k = n-1; k > 0 ; k--){
			*(a + k) = *(a + k - 1);
		}
		*a = r;
	}
}
void out(int a[],int n) {
	for (int i = 0; i < n; i++){
		printf("%d", *(a + i));
		if (i!=n-1) printf(" ");
	}
}
int main() {
	int a[100],n,ch;
	scanf_s("%d%d", &n, &ch);
	ch = ch % n;
	input(a, n);
	change(a, n, ch);
	out(a, n);
}

这里用了指针来传递数组,其他就没什么的了,总体还是挺简单的。

以后的题目中我会加入一些注释解释一些比较复杂的算法,如果大家还有什么想问的欢迎在评论区留言。如果有更好的算法想要分享也可以在评论区留言呀

你可能感兴趣的:(C语言,高级语言程序设计,程序设计,算法,c语言)