吉林大学软件学院期末题答案(10-16级)

2016级A卷

1.编写函数并画出对应的PAD,将整形数组a中的所有元素逆序存放。函数声明为:void rev(int a[ ],int n)

void rev(int a[ ],int n)
{
	int left = 0, right = n - 1;
	while(left < right)
	{
		int temp = a[left];
		a[left] = a[right];
		a[right] = temp;
		left++;
		right--;
	}
}
void rev(int a[ ],int n)
{
	for(int i =0; i < n / 2; i++)
	{
		int temp = a[i];
		a[i] = a[n-i-1];
		a[n-i-1] = temp;
	}
}

2.编写函数,比较两个字符串,返回其长度的差值。函数声明为:int comp(char a,char b)
注意,不允许使用string.h头文件和其声明的相关函数

int comp(char *a, char *b)
{
	int num1 = 0, num2 = 0;
	while(*a != '\0')
	{
		num1++;
		a++;
	}
	while(*b != '\0')
	{
		num2++;
		b++;
	}
	return num1 - num2;
}

3.一个长度为n(n>5),可以在其2/5处折断,变为两段长度分别为2n/5,3n/5的木条;如果得到的木条的长度仍大于五,则继续按照上述方法折断,直到任意木条的长度均不大于5为止。编写递归函数,计算一个长度为n的木条,最后会被折断为多少根木条。

int f(double n)
{
	if(n <= 5)	注意,并非求折断的次数
		return 1;
	return f(2*n/5) + f(3*n/5);
}

4.每个学生的信息卡片包括学号,姓名和联系电话三项,要求:
1)定义存储学生信息的单向链表的结点类型;
2)编写函数,由键盘依次输入n(n>=0)个学生的信息,创建一个用于管理学生联系方式的单向链表,并在创建过程中随时保证该单向链表的节点顺序满足学号从低到高的顺序。
注:必须包含且仅包含与该题目相关的头文件。

#include 
#include 
struct ListNode{
	int num;			//学号
	char name[20];		//姓名 
	int tel[10]; 		//联系电话 
	struct ListNode* next;
};
struct ListNode* create(int n)
{
	struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
	head -> next = NULL;
	struct ListNode* pre = head;
	for(int i = 0; i < n; i++)
	{
		struct ListNode* p = (struct ListNode*)malloc(sizeof(struct ListNode));
		printf("请输入姓名\n");
		scanf("%s",p->name);
		printf("请输入学号\n");
		scanf("%d",&p->num);
		printf("请输入电话号码\n");
		scanf("%s",p->tel);
		while(pre -> next != NULL && pre -> next -> num < p -> num)
			pre = pre -> next;
		p -> next = pre -> next;
		pre -> next = p;
	}
	return head -> next;
}

五、编写函数,将第四题中构建的单向链表中的全部信息写入磁盘D:盘根目录下的address.txt文件中,要求:每次写入一个学生的信息,就从键盘输入该学生的家庭住址,把家庭住址同时写入文件中。
注:必须包含且仅包含与该题相关的头文件。

void WriteToFile(struct ListNode* head)
{
	FILE* fp;
	char *address;
	struct ListNode* p = head;
	if((fp = fopen("D://address.txt","w")) == NULL)
	{
		printf("can not open the address.txt\n");
		exit(0);
	}
	while(p != NULL)
	{
		fprintf(fp,"%25s %10d %25s",p -> name,&p -> num,p -> tel);
		printf("请输入家庭地址\n"); 
		scanf("%s",address);
		fprintf(fp,"%25s\n",address);	
		p = p -> next;
	}
	fclose(fp);
}

2016级唐班A卷

1.编写函数,将两个非递减整形数组a和b合并后存储在a中,并保证处理后的数组仍然按照非递减顺序存储,函数返回值为出现次数最多的元素值,不能定义额外的新数组。
函数声明为:

int merge(int *a ,int m, int *b, int n)

算法思想:
1.比较a和b两个数组元素,对a数组进行插入数组b中的元素,需要进行n次插入,因此设置数器count表示插入的次数
2.遍历数组a,每当遇到元素的值大于当前数组b的值时,将数组a中所有元素向后移动一个单位
3.遍历结束后,数组b有可能未插入完毕,则将剩余部分插入到数组a的后面
4.重新遍历一次数组,求出现最多的元素值

int merge(int *a ,int m, int *b, int n)
{
	int count = 0;
	for(int i = 0; i < m && count < n; i++)
	{
		if(a[i] > b[count])		//当出现大于当前b数组的元素时 
		{
			for(int j = m; j > i; j--)	//所有元素向后移动一个单位 
				a[j] = a[j - 1];
			a[i] = b[count++];
			m++;						//数组元素个数更新 
		}
	}
	for(; count < n; count++)			//对末尾部分进行复制 
		a[m++] = b[count];
	int times = 1, max = 0; 
	int loc = 0, i;
	for(i = 1; i < m; i++)
	{
		if(a[i-1] == a[i])
			times++;
		else
		{
			if(times > max)
			{
				max = times;
				loc = i-1;	
			}
			times = 1;
		}
	}
	if(times > max)	//对结尾段进行判断
		loc = i - 1;
	return a[loc];
}

2.编写函数,求一个字符串的最小字符。函数声明为:
char minchar (char *a)

char minchar(char *a)
{
	char min = a[0];
	while(*a != '\0')
	{
		if(*a < min)
			min = *a;
		a++;
	}
	return min;
}

3.(2x+3y)的n次幂的二项式展开有n+1项,按照x的指数降序排列。编写递归函数,返回该展开的第k(0 <= k <= n)项的系数。递归函数的参考形式为int find(int n ,int k)。

算法思想:
1.2x+3y)的n次幂二项式系数的第k项 =2x+3y)的 n-1 次幂二项式系数的第k项 乘 2 +2x+3y)的 n-1 次幂二项式系数的第 k-1 项 乘3
原因在于,在(2x+3y)的n次幂中选择了2x这一项,那么在(2x+3y)的 n-1 次幂中只需要再选第k项即可(此时第k项系数中x的幂比递归前少1)
而(2x+3y)的n次幂中选择了3y一项时,仍需选择与递归前次方相同的一项,因此需要选择高一阶的 第k-12. 当k = n时,说明是(2x+3y)的n次方中第n项,即常数项系数
   当k = n = 0时,说明(2x+3y)的0次方的第0次项,返回1
   当k = 0时,说明需要返回(2x+3y)的n次方中最高阶的系数
故有如下等式
find(n,k) =     1                                           k = n = 03 * find(n - 1, k - 1)                      k = n时
                2 * find(n - 1, k)                          k = 02 * find(n - 1,k) + 3 * find(n - 1, k - 1)  其它
                
int find(int n, int k)
{
	if(n == k && k == 0)	return 1;
	if(n == k) 				return 3*find(n-1,k-1);
	if(k == 0)				return 2*find(n-1,k);
	return 2*find(n-1,k)+3*find(n-1,k-1);	
} 

4.CCF会员的信息卡至少包括:会员号(5位数字+1位大写字母)、姓名、会员类别、有效期(包含年、月、日)等信息
例如:15316S、吕帅、高级会员、20181231
1)定义存储CCF会员上述信息的单向链表结点类型;
2)编写函数,依次由文件in.txt读入所有会员的信息(文件中每个会员信息包括会员号、姓名、有效期);会员类别为冗余信息,由会员号的最后一位可以推导出,创建一个用于管理会员信息的单向链表,使该链表有序;
3)假定管理会员的单向链表已经按照会员号的五位数字(唯一标识)从小到大排序。编写函数,将该单向链表修改为:首先按照会员类别排序,相同类别的会员按照5位数字从小到大排序。

#include 
#include 
struct LinkNode{
	int num;		//会员号数字信息 
	char kind;		//会员号大写字母信息,表示类别
	char name[30];	//姓名
	int date;		//有效期
	struct LinkNode* next;
}; 
struct LinkNode* creat()
{
	FILE *fp;
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* pre = head;
	if((fp = fopen("in.txt","r")) == NULL)
		printf("can not open the file\n");
	while(!feof(fp))
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		fscanf(fp,"%d %c",&p->num,&p->kind);
		fscanf(fp,"%s",p->name);
		fscanf(fp,"%d",&p->date);
		while(pre -> next != NULL && pre ->next -> num < p -> num)
			pre = pre -> next;
		p -> next = pre -> next;
		pre -> next = p;
		pre = head;
	}
	fclose(fp);
	return head -> next;
}
struct LinkNode* sort(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = NULL;
	struct LinkNode* pre = dummyhead, *p = head;
	while(p != NULL)
	{
		struct LinkNode* temp = p -> next;
		while(pre -> next != NULL && pre -> next -> kind < p -> kind)	//先找到同类型的 
			pre = pre -> next;
		if(pre -> kind == p -> kind)									//若已经找到了同类型的 
			while(pre -> next != NULL && pre -> next -> num < p -> num)	//再找第一个会员号排序比它大的 
				pre = pre -> next;
		p -> next = pre -> next;
		pre -> next = p;
		pre = dummyhead;
		p = temp;
	}
	return dummyhead -> next;
}

2016级B卷

1.编写函数,实现按照如下公式计算的功能:
f(n)=0/(1*2!)+1/(2*3!)+2/(3*4!)+……+n/((n+1)*(n+2)!)
其中n为自然数。

int fac(int n)
{
	if(n == 1)	return 1;
	return n * fac(n-1);
}
float caculator(int n)
{
	float sum = 0;
	for(int i = 0; i <= n ; i++)
	{
		sum += (1.0 * i) / ((i + 1) * fac(i+2));
	}
	return sum;
}

2.编写bool函数,判断给定的整数数组a[n]中是否存在元素a[i],i的取值范围为0到n,等于其前边所有元素之和,即a[i]=a[0]+a[1]+a[2]+a[3]+…a[i-1]

bool isExist(int a[], int n)
{
	int sum = a[0];
	for(int i = 1; i < n; i++)
	{
		if(a[i] == sum)
			return true;
		sum += a[i];
	}
	return false;
}

3.编写一个递归函数,计算组成给定正整数n的所有数字之和。
例如:给定参数为1035,则返回结果应该为9(通过1+0+3+5=9获得)

int f(int n)
{
	if(n == 0)	
	return 0;
	return n % 10 + f(n / 10);
}

4.构造一个表示教师的结构体(包含三个字段,姓名,性别,年龄),编写函数,读入M个教师的信息,存入一个结构体数组中,如下图所示:
在这里插入图片描述
例如:一个教师的信息为Zhangsan、true、50,另一个教师的信息为Lisi、false、37。

#include 
struct teacher{
	char name[10];
	bool sex;
	int age;
};
void save(struct teacher st[], int M)
{
	for(int i = 0; i < M; i++)
	{
		scanf("%s",st[i].name);
		scanf("%d",&st[i].sex);
		scanf("%d",&st[i].age);
	}
}

五、设有一个保存教师信息的单链表,(每个结点包含四个字段:姓名,性别,年龄,后继指针),构造该链表中一节的数据类型声明:编写函数,在给定链表上查找所有女教师的信息,并存储到指定文件output.txt中。

#include 
#include 
struct LinkNode{
	char name[30];	//姓名
	bool sex;		//性别,男性为true,女性为false
	int age;		//年龄
	struct LinkNode* next;
};
void save(struct LinkNode* head)
{
	FILE *fp;
	if((fp = fopen("output.txt","w")) == NULL)
		printf("can not open the output.txt\n");
	struct LinkNode* p = head;
	while(p != NULL)
	{
		if(p -> sex == false)
		{
			fprintf(fp,"%s",p->name);
			fprintf(fp,"%d",p->age);	
		}
		p = p -> next;
	}
	fclose(fp);
}

2016级唐班B卷

1.编写函数,将两个非递减整形数组a和b合并后存储在a中,并保证处理后的数组仍然按照非递减顺序存储,函数返回值为出现次数最多的元素值,不能定义额外的新数组。
函数声明为:int merge(int *a ,int m, int *b, int n)

答案同2016级唐班A卷第一题

2.编写函数,求一个正整数的最小质因数

int find(int n)
{
	for(int i = 2; i <= n; i++)
	{
		if(n % i == 0)
			return i;
	}
}

3.一个长度为n(n>5),可以在其2/5处折断,变为两段长度分别为2n/5,3n/5的木条;如果得到的木条的长度仍大于五,则继续按照上述方法折断,直到任意木条的长度均不大于5为止。编写递归函数,计算一个长度为n的木条,最后会被折断为多少根木条。

答案同2016级A卷第三题

4.CCF会员的信息卡至少包括:会员号(5位数字+1位大写字母)、姓名、会员类别、有效期(包含年、月、日)等信息
例如:15316S、吕帅、高级会员、20181231
1)定义存储CCF会员上述信息的单向链表结点类型;
2)编写函数,依次由文件in.txt读入所有会员的信息(文件中每个会员信息包括会员号、姓名、有效期);会员类别为冗余信息,由会员号的最后一位可以推导出,创建一个用于管理会员信息的单向链表,使该链表有序;
3)编写函数,将上述链表逆序。

前两问答案同2016唐班A卷第四题,第三问代码如下

递归法
struct LinkNode* reverse(struct LinkNode* head)
{
	if(head == NULL || head -> next == NULL)
		return head;
	struct LinkNode* p = reverse(head -> next);
	head -> next -> next = head;
	head -> next = NULL;
	return p;
}
迭代法
struct LinkNode* reverse(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = NULL;
	while(head != NULL)
	{
		struct LinkNode* temp = head -> next;
		head -> next = dummyhead -> next;
		dummyhead -> next = head;
		head = temp;
	}
	return dummyhead -> next;
}

2015级唐班A卷

1.编写函数,将一个十进制整数转换为二进制输出。

#include 
void change(int n)
{
	int a[20] = {0}, k = 0;
	while(n != 0)
	{
		a[k++] = n % 2;
		n /= 2;
	}
	for(int i = k - 1; i >= 0; i--)
		printf("%d ",a[i]);
}
void change2(int n)
{
	if(n > 1)
		change(n/2);
	printf("%d",n % 2);
}

2.编写函数 int mergearr (int a[], int m, int b[], int n),将两个严格增序数组a和b合并后存储在a中,并保证处理后的数组仍然严格增序,函数值返回合并后数组a中的元素个数,不能定义额外的新数组。

#include 
int merge(int a[], int m, int b[], int n)
{
	int count = 0;
	for(int i = 0; i < m && count < n; i++)
	{
		if(a[i] > b[count])
		{
			for(int j = m; j > i; j--)
				a[j] = a[j - 1];
			a[i] = b[count++];
			m++;			
		}
		else if(a[i] == b[count])	//相同元素直接跳过
			count++;
	}
	for(count; count < n; count++)
		a[m++] = b[count++];
	return m;
}

3.给定一个凸n边形(n>=3),可以用n-3条不相同的对角线把它剖分成n-2个三角形。编写递归函数,计算凸n边形的三角形剖分数(不同剖分方法的个数)。提示,递归公式如下:
吉林大学软件学院期末题答案(10-16级)_第1张图片

#include 
int f(int n)
{
	if(n == 2)
		return 1;
	int sum = 0;
	for(int i = 2; i <= n-1; i++)
		sum += f(i)*f(n+1-i);
	return sum;
}

4.职工的信息卡至少包括工号、姓名出生年月等信息。限定:工号为整形且不超过整形的取值范围。
1)定义存储职工信息的单向链表的节点类型;
2)编写函数,由文件in.txt中依次读入k个职工的完整信息,创建一个用于管理职工信息的单向链表;
3)假定管理职工信息的单向链表已经按照工号从小到大排序。编写函数,由键盘键入1个职工的信息,按工号顺序插入到用于管理职工信息的单向链表中。

#include 
#include 
struct date{
	int year, month;		//年,月 
}; 
struct LinkNode{
	int num;				//工号
	char name[30];			//姓名
	struct date birth;		//出生年月 
	struct LinkNode* next;
};
struct LinkNode* Creat(int k)
{
	FILE *fp;
	if((fp = fopen("D:\\in.txt","r")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);
	}
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* rear = head;
	for(int i = 0; i < k; i++)
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		fscanf(fp,"%d %s %d %d",&(p->num),p->name,&(p->birth.year),&(p->birth.month));
		p -> next = rear -> next;
		rear -> next = p;
		rear = p;
	}
	fclose(fp);
	return head -> next;
}
struct LinkNode* Insert(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode* pre = dummyhead;
	struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	printf("请输入工号,姓名,生日\n");
	scanf("%d %s %d %d",&(p -> num),p -> name, &(p -> birth.year),&(p -> birth.month));
	while(pre -> next != NULL && pre -> next -> num < p -> num)
		pre = pre -> next;
	p -> next = pre -> next;
	pre -> next = p;
	return dummyhead -> next;
}

2015级唐班B卷

1.编写函数,按照如下公式计算圆周率π的值(精确到1e-5)
在这里插入图片描述

#include 
double pai()
{
	double sum = 0, temp = 1;
	int n = 1;
	while(temp - sum >= 1e-5)
	{
		sum = temp;
		temp *= 1.0 * (2 * n) * (2 * n) / (2 * n - 1) / (2 * n + 1);
		n += 1;
	}
	return 2*sum;
}

2.编写函数int delarr(int a[], int n),删除整型数组a中所有偶数,要求:a数组中剩余元素保存次序顺序存储,函数值返回剩余偶数个数,不能定义额外的新数组

#include 
int delarr(int a[], int n)
{
	int k = 0;	//k为数组中奇数的个数
	for(int i = 0; i < n; i++)
		if(a[i] % 2 != 0)
			a[k++] = a[i];
	return k;
}

3.给一个正整数n,将其拆分为n个1。可行的拆分过程为:(设定一个初值为0的累加器)。首先,将n拆分为2个数,两个数之和为n,二者之差的绝对值加入累加器中:再对拆分得到的2个数分别进行上述“拆分+累加”操作,直到所有数均拆分为1为止。编写递归程序,计算所有可行拆分过程所对应的的累加器的最小值。提示:递归公式如下

#include 
int f(int n)
{
	if(n == 1)
		return 0;
	int min = f(n-1) + n - 2;	//将i等于1代入表达式作为初始最小值 
	for(int i = 2; i <= n/2; i++)
	{
		int temp = n - i - i + f(i) + f(n - i);
		if(temp < min)
			min = temp;
	}
	return min;
}

4.职工的信息卡至少包括工号、姓名出生年月等信息。限定:工号为整形且不超过整形的取值范围。
1)定义存储职工信息的单向链表的节点类型;
2)假定管理职工信息的单向链表已经从小到大排序,编写函数,由键盘键入1个职工的工号,删除该职工的全部信息
3)编写函数,将职工信息的单向链表中所有出生月份大于y的职工的完整信息,存储到文件out.txt中

#include 
#include 
struct date{
	int year, month;		//年,月 
}; 
struct LinkNode{
	int num;				//工号
	char name[30];			//姓名
	struct date birth;		//出生年月 
	struct LinkNode* next;
};
struct LinkNode* Delete(struct LinkNode* head)
{
	int key;
	printf("please input the num which needs delete\n");
	scanf("%d",&key);
	if(head -> num == key)	//若删除的节点为头节点 
		return head -> next;		
	struct LinkNode *p = head -> next, *pre = head;
	while(p != NULL && p -> num != key)
	{
		pre = p;
		p = p -> next;
	}
	if(p != NULL)
		pre -> next = p -> next;
	return head;
}
void save(struct LinkNode* head, int birthyear)
{
	FILE *fp;
	if((fp = fopen("D:\\out.txt","w")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);
	}
	struct LinkNode* p = head;
	while(p != NULL)
	{
		if(p -> birth.year > birthyear)
			fprintf(fp,"%d %s %d %d\n",p -> num,p -> name, p -> birth.year,p -> birth.month);
		p = p -> next;
	}
	fclose(fp);
}

2014级A卷

1.编写函数 int delarr(int a[] ,int n),并画出对应的PAD,删除有n个元素的正整型数组a中所有素数,要求:
1)数组a中剩余元素保持原来次序;
2)将处理后的数组输出;
3)函数值返回剩余元素个数;
4)不能额外定义新数组。

#include 
#include 
bool isPrime(int n)
{
	for(int i = 2; i <= sqrt(n); i++)
		if(n % i == 0)
			return false;
	return true;
}
int delarr(int a[] ,int n)
{
	int k = 0;	//k为数组中奇数的个数
	for(int i = 0; i < n; i++)
		if(!isPrime(a[i]))
			a[k++] = a[i];
	for(int i = 0; i < k; i++)
		printf("%4d",a[i]);
	return k;
}

2.编写函数bool cmpstr(char *s),判定一个给定字符串s是否对称,对称字符串也成为回文,是满足从左到右和从右到左均相同的字符序列(不考虑默认字符串结尾’\0’)

bool cmpstr(char *s)
{
	int len = 0;
	while(s[len] != '\0')
		len++;
	for(int i = 0; i < len / 2; i++)
		if(s[i] != s[len-1-i])
			return false;
	return true;
}

bool cmpstr(char *s)
{
	int len = 0;
	while(s[len] != '\0')
		len++;
	int left = 0, right = len - 1;
	while(left < right)
	{
		if(s[left] != s[right])
			return false;	
		left++;
		right--;		
	}
	return true;
}

3.编写递归函数float comp(float a[],int n),计算给定n个元素的float型数组中所有元素的算术平均值。

算法思想:
1.comp(a,n)代表求n个数的平均值, comp(a, n - 1) * (n - 1)表示n-1个数的和,再加上a[n-1]就是n个数的和,同时除以5表示算数平均值
2.当n等于1时代表只有一个数,直接返回该数即可

#include 
float comp(float a[],int n)
{
	if(n == 1)
		return a[0];
	return (comp(a, n - 1) * (n - 1) + a[n - 1]) / n;	
}

4.每个学生的信息卡片包括学号、姓名、年龄三项。定义存储学生信息的单向链表的节点类型;编写函数,由键盘依次输入n个学生的信息,创建一个用于管理学生信息的单向链表。
5.编写函数,把上中创建的单向链表中所有年龄为z的结点删除(z的指由用户键盘输入,且年龄为z的结点可能有多个),将处理后的单向链表的所有学生信息存储到名为output.txt的文本文件中。

#include 
#include 
struct LinkNode{
	int num;				//工号
	char name[30];			//姓名
	int age;				//年龄 
	struct LinkNode* next;
};
struct LinkNode* Creat(int n)
{

	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* rear = head;
	for(int i = 0; i < n; i++)
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		printf("Please input the information\n");
		scanf("%d %s %d",&(p->num),p->name,&(p->age));
		rear -> next = p;
		rear = p;
	}
	rear -> next = NULL;
	return head -> next;
}
void DelAndSave(struct LinkNode* head, int z)
{
	FILE *fp;
	if((fp = fopen("D:\\output.txt","w")) == NULL)
	{
		printf("can not open the output.txt\n");
		exit(0);
	}
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode* p = head, *pre = dummyhead;
	while(p != NULL)
	{
		if(p -> age == z)
		{
			pre -> next = p -> next;
			p = p -> next;
		}
		else
		{
			pre = p;
			p = p -> next;	
		}
	}
	p = dummyhead -> next;
	while(p != NULL)
	{
		fprintf(fp,"%d %s %d\n",p->num,p->name,p->age);
		p = p -> next;
	}
	fclose(fp);
} 

2014级唐班A卷

1.编写递归函数float comp(float a[][2], int n),计算两个给定n维向量u,v的内积。a的每行为一个向量,函数值为计算出的内积。

#include 
float comp(float a[][2], int n)
{
	if(n == 0)
		return 0;
	return comp(a,n-1) + a[n-1][0] * a[n-1][1];
}

2.编写函数int changestr(char s),把给定字符串s修改为回文字字符串。修改方法是:以左半段为基本字符串,把右半段修改成左半段的反序(不考虑结尾字符串结束符’\n’)。函数值带回结果字符串长度。设对应s的实在参数是一个字符串。
例:字符串“aba”,“a a”和“abcacba”均为回文字,而“ab”不是回文字
注:本题不允许使用string.h头文件和相关的字符串处理函数,不允许再声明其他数组。

#include 
int changestr(char *s)
{
	int len = 0, left, right;
	while(s[len] != '\0')	//求出字符串长度 
		len++;
	left = 0;
	right = len - 1;
	while(left < right)
	{
		s[right] = s[left];
		left++;
		right--;
	}
	return len;
}

3.编写函数int delarr(int a[][10], int n),删除n行10列两维正整型数组a中所有素数,要求:
1)a数组中剩余元素保持原来次序
2)将处理后的数组最后一个有效元素位置的行、列号删除
3)函数值返回剩余元素个数
4)不能定义额外的新数组

//	算法思想:设置非质数的个数为k,每当遇到非质数,将a[k / 10][k % 10] 赋值为a[i][j] 
#include 
#include 
bool isPrime(int n)
{
	if(n <= 1)
		return false;
	for(int i = 2; i <= sqrt(n); i++)
		if(n % i == 0)
			return false;
	return true;
}
int delarr(int a[][10], int n)
{
	int k = -1;	//k表示实际上二维数组a剩余的元素个数
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < 10; j++)
			if(!isPrime(a[i][j]))
			{
				k++;
				a[k / 10][k % 10] = a[i][j];
			}	
	}
	printf("最后一个有效元素的下标为%d %d\n",k / 10,k % 10 - 1);	//下标需要减少1
	return k;
}

4.职工的信息卡内容包括:工号(字符串型)、姓名(字符串型)和出生时间(结构体型,包括年、月、日)三项
1)定义存储职工信息的单向链表的结点类型;
2)编写函数,由键盘依次输入职工的信息,按工号顺序创建一个用于管理职工信息的单向链表。直到输入的工号为“0000”为之。要求边录入边建立链表,不允许先建立链表后,再排序。
5.编写函数,把上题创建的单向链表存储到文件名为output.dat的二进制文件中。

#include 
#include 
#include 
struct date{
	int year, month, day;
};
struct LinkNode{
	char num[30];
	char name[30];
	struct date birth;
	struct LinkNode* next;
};
struct LinkNode* creat()
{
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* pre = head;
	char str[30];
	printf("Please input the id\n");
	scanf("%s",str);
	while(strcmp(str,"0000"))
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		strcpy(p->num,str);
		scanf("%s %d %d %d",p->name,&(p->birth.year),&(p->birth.month),&(p->birth.day));
		while(pre -> next != NULL && strcmp(p -> num,pre -> next -> num) == 1)
			pre = pre -> next;
		p -> next = pre -> next;
		pre -> next = p;
		pre = head;
		scanf("%s",str);	
	}
	return head -> next;
}
void save(struct LinkNode* head)
{
	FILE* fp;
	if((fp = fopen("output.dat","wb")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);
	}
	struct LinkNode* p = head;
	while(p != NULL)
	{
		fprintf(fp,"%s %s %d %d %d\n",p->num,p->name,p->birth.year,p->birth.month,p->birth.day);
		p = p -> next;
	}
	fclose(fp);
}

2014级B卷

1.编写函数并画出对应的PAD,删除整形数组中所有为0的元素,将处理后的数组输出,并返回剩余元素个数。
注意:函数中不能定义额外的新数组。

#include 
int delete0 (int a[], int n)
{
	int k = 0;
	for(int i = 0; i < n; i++)
		if(a[i] != 0)
			a[k++] = a[i];
	return k;
}

2.编写函数,对一个给定字符串中的所有字符(不考虑默认字符串结束符’\0’)进行排序,使得排序后的字符串满足从左到右为ASCLL码递增的字符序列。
注:本题中不准使用string.h头文件和相关的字符串处理函数,以及系统定义的各类排序函数。

#include 
void bubblesort(char *s)
{
	int len = 0;
	while(s[len] != '\0')	len++;
	for(int i = len - 1; i > 0; i--)
		for(int j = 0; j < i; j++)
			if(s[j] > s[j+1])
			{
				char temp = s[j];
				s[j] = s[j+1];
				s[j+1] = temp;
			}
}
void selectsort(char *s)
{
	int len = 0;
	while(s[len] != '\0')	len++;
	for(int i = 0; i < len - 1; i++)
	{
		int min = i;
		for(int j = i + 1; j < len; j++)
			if(s[j] < s[min])
				min = j;
		char temp = s[i];
		s[i] = s[min];
		s[min] = temp;
	}
}
void insertsort(char *a)
{
	int len = 0;
	while(a[len] != '\0')	len++;
	int i, j;
	for(i = 1; i < len; i++)
	{
		j = i - 1;				
		char temp = a[i];		//保存a[i] 
		while(j >= 0 && temp < a[j])	//从i位置的前一个元素开始找第一个小于a[i]的元素
		{
			a[j+1] = a[j];				//元素向后移动一个单位 
			j--;
		}
		a[j+1] = temp;					//插入a[i] 
	}
}

3.编写递归函数,计算给定数组中所有元素的中位数,中位数标准定义为:按照从小到大排序后正中间的数。如果元素个数为偶数,取最中间的两个数的平均数作为中位数。本题可以粗略地认为n个元素的中位数为按照从小到大排序后的第n/2个数。

#include 
//利用递归,每次去除一个最大值,将其放在最后,直至去除了N/2个最大值,当前的最大值就是中位数 
int f(int a[], int n, int mid)
{
	if (n == mid)
		return a[n];
	int max = 0;
	for (int i = 0; i < n; i++)
		if (a[i] > a[max])
			max = i;
	int temp = a[max];	//将最大值放在最后
	a[max] = a[n-1];
	a[n-1] = temp;
	return f(a, n - 1, mid);
}

4.每个教师的信息卡片包括教工号、姓名、性别、入职年份(限定为1900-2100之间的整数)四项。定义存储教师信息的单向链表的结点类型;编写函数,由当前目录下文件名为:input.txt的文件依次读入n个教师的信息,创建一个用于管理信息的单向链表。
5.编写函数,在上题创建的单向链表中删除所有入职年份大于k(k的值由用户从键盘输入,且限定为1900-2100之间的整数)的结点。

#include 
#include 
struct LinkNode{
	int num;
	char name[30];
	int sex;
	int year;
	struct LinkNode* next;
};
struct LinkNode* creat(int n)
{	
	FILE *fp;
	if((fp = fopen("input.txt","r")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);
	}
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* rear = head;
	for(int i = 0; i < n; i++)
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		fscanf(fp,"%d %s %d %d",&(p->num),p->name,&(p->sex),&(p->year));
		p -> next = rear -> next;
		rear -> next = p;
		rear = p;
	}
	fclose(fp);
	return head -> next;
}
struct LinkNode* del(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode *pre = dummyhead, *p = head;
	printf("Please input the year which needs delete\n");
	int y;
	scanf("%d",&y);
	while(p != NULL)
	{
		if(p -> year <= y)
		{
			pre = p;
			p = p -> next;
		}
		else
		{
			pre -> next = p -> next;
			p = p -> next;
		}
	}
	return dummyhead -> next;
}

2014级唐班B卷

1.编写函数,输出给定的字符串s中从m字符开始后的r个字符(假设s中有m字符且后有r个字符)。

#include 
void f(char *s, int r)
{
	int i = 0;
	while(s[i] != 'm')	i++;
	for(int j = 0; j < r; j++)
		printf("%c",s[++i]);
}

2.有n个整数放在数组a中,编写递归函数,求整数之和。

#include 
int f(int a[], int n)
{
	if(n == 0)
		return 0;
	return a[n-1] + f(a,n-1);
}

3.编写函数,对任意给定的int类型数组A,求最小元素值并输出。求最小元素用函数编写,以指针做参数。函数形式如下 int min_data(int *p, int n)
其中:指针p为数组首地址,n为数组元素个数

#include 
int min_data(int *p, int n)
{
	int min = p[0];
	for(int i = 1; i < n; i++)
		if(p[i] < min)
			min = p[i];
	return min;
}

4.在D盘根目录下有文件source.txt,在该文件中存放某班学生的学号及成绩,每个学生的学号是唯一的,学号和成绩是整数,每个数据宽度为6位,编写程序求:
从键盘输入学生的学号,在文件中检索该学生:如找到,显示该学生的学号及成绩;不存在显示-1.

#include 
#include 
int main()
{
	FILE *fp;
	if((fp = fopen("D:\\source.txt","r")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);	
	}
	int num, score, key;
	scanf("%d",&key);
	while(!feof(fp))
	{
		fscanf(fp,"%6d%6d",&num,&score);
		if(key == num)
		{
			printf("%6d%6d\n",num,score);
			return 0;
		}
	}
	printf("-1\n");
	fclose(fp);
} 

5.已知如图所示一个链表,链表的每节是一个字符,要求:
1)根据给定的链表定义结点的结构体类型
2)编写函数删除链表中所有数字字符的结点

#include 
#include 
struct LinkNode{
	char key;
	struct LinkNode* next;
};
struct LinkNode* del(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode *pre = dummyhead, *p = head;
	while(p != NULL)
	{
		if(p -> key >= '0' && p -> key <= '9')
		{
			pre -> next = p -> next;
			p = p -> next;
		}
		else
		{
			pre = p;
			p = p -> next;
		}
	}
	return dummyhead -> next;
}

2013级A卷

1.画PAD图,无需掌握

2.编写函数,实现按照如下公式计算的功能
在这里插入图片描述

#include 
int fac(int n)
{
	if(n <= 1)
		return 1;
	return n * fac(n-1);
}
double f(int n)
{
	double sum = 0;
	for(int i = 2; i <= n; i++)
		sum += 1.0 * i / ((i + 1) * fac(i - 2));
	return sum;
}

3.编写一个函数,按照如下定义计算Hermite多项式的函数,公式递归定义如下

在这里插入图片描述

double Herrnite(int n, int x)
{
	if(n == 0)	return 1;
	if(n == 1) 	return 2 * x;
	return 2 * x * Herrnite(n-1,x) - 2 * (n - 1) * Herrnite(n-2,x);
}

4.定义存储学生信息的结构体至少应包含:学号、姓名、成绩、指向下一个结构体的指针等字段。编写函数,从指定文件class531316.txt中读入所有学生信息,(假定文件中存储信息与结构体信息格式对应),构建为图1所示的链表。

#include 
#include 
struct LinkNode{
	int num;			//学号
	char name[30]; 		//姓名 
	int score;			//成绩 
	struct LinkNode* next;
};
struct LinkNode* creat()
{	
	FILE *fp;
	if((fp = fopen("D:\\class531316.txt","r")) == NULL)
	{
		printf("can open the file\n");
		//exit(0);	
	} 
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* rear = head;
	while(!feof(fp))
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		fscanf(fp,"%d %s %d",&(p->num),p->name,&(p->score));
		p -> next = rear -> next;
		rear -> next = p;
		rear = p;
	}
	return head -> next;
}

5.给定图2所示的链表,每个结点包含:整数信息key和后继指针next。编写函数,删除该链表中的具有最大key值和最小key值得结点(注:key值可能重复)
例如,若链表中存储的key值依次为1、0、3、5、2、5、3、0、7、9、1,最大key值为9,最小key值为0,则处理后的链表中存储的key值为1、3、5、2、5、3、7、1。

#include 
#include 
struct LinkNode{
	int key;
	struct LinkNode* next;
};
struct LinkNode* del(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode *maxp = head, *minp = head;
	struct LinkNode *p = head, *pre;
	while(p != NULL)	//扫描一遍链表记录最大值和最小值结点的值 
	{
		if(p  -> key < minp -> key)
			minp = p;
		if(p -> key > maxp -> key)
			maxp = p;
		p = p -> next;
	}
	p = head;
	pre = dummyhead;
	while(p != NULL)
	{
		if(p -> key == minp -> key || p -> key == maxp -> key)
			pre -> next = p -> next;
		else
			pre = p;
		p = p -> next;
	}
	return dummyhead -> next;
}

2013级B卷

1.画PAD图,无需掌握
2.编写函数,实现按照如下公式计算的功能
在这里插入图片描述
其中n为自然数且n>=0,0!=1。

#include 
int fac(int n)
{
	if(n <= 1)
		return 1;
	return n * fac(n-1);
}
double f(int n)
{
	double sum = 0, temp = 1;
	for(int i = 0; i <= n; i++)
	{
		sum += 1.0 * fac(i) / temp;
		temp *= 2;
	}
	return sum;	
}

3.编写递归函数,输出一个正整数的所有质因数(质因数分解中得到的重复质因子需要多次输出)。
例如:1没有质因数;2的质因数为2;18的质因数为2、3和3;48的质因数为2、2、2、2和3。

#include 
void f(int n)
{
	if (n == 1)
		return;
	for (int i = 2; i <= n; i++)
		if (n % i == 0)
		{
			printf("%d ", i);
			f(n / i);
			return;
		}
}

4.定义存储学生信息的结构体至少应包含:学号、姓名、成绩、指向下一个结构体的指针4个字段。编写函数,将图1所示的链表中成绩不及格(0-59分)的学生人数和不及格学生的全部信息存储到指定文件class531316.txt中。

#include 
#include 
struct LinkNode{
	int num;			//学号
	char name[30]; 		//姓名 
	int score;			//成绩 
	struct LinkNode* next;
};
void save(struct LinkNode* head)
{
	FILE *fp;
	if((fp = fopen("class531316.txt","w")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);	
	}
	struct LinkNode *p = head;
	int count = 0;
	while(p != NULL)
	{
		if(p -> score >= 0 && p -> score <= 59)
		{
			fprintf(fp,"%d %s %d\n",p->num,p->name,p->score);
			count++;
		}
		p = p-> next;
	}
	fprintf(fp,"不及格人数为%d人",count);
	fclose(fp);
} 

5.给定图2所示的链表,每个结点包含:整数信息key和后继指针next。编写函数,对该链表进行排序,使得处理后的链表保持非降序。
例如:若链表中存储的key值依次为1、0、3、3、0、7、9、1,则处理后的链表中存储的key值依次为0、0、1、1、3、3、7、9。

#include 
#include 
struct LinkNode{
	int key;			
	struct LinkNode* next;
};
struct LinkNode* insertsort(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = NULL;
	struct LinkNode *pre = dummyhead, *p = head;
	while(p != NULL)
	{
		struct LinkNode* temp = p -> next;
		while(pre -> next != NULL && pre -> next -> key < p -> key)
			pre = pre -> next;
		p -> next = pre -> next;
		pre -> next = p;
		pre = dummyhead;
		p = temp;
	}
	return dummyhead -> next;
}

2012级A卷

1.编写函数,输出任意正整数n的位数(n默认为存储十进制的整形变量)
例如:正整数13,则输出2,;正整数3088,则输出4

#include 
int f(int n)
{
	if(n == 0)
		return 0;
	return f(n / 10) + 1;
}

2.编写函数,对给定有序整形数组进行整理,使得所有整数只保留一次出现。
例如:原数组为-2、-2、-1、0、0、1、4、4、4,则处理后的结果为-2、-1、0、1、4

#include 
int DuplicateRemovl(int a[], int n)
{
	int k = 0;	//k表示不重复的下标
	for(int i = 1; i < n; i++)	//第一个元素默认不重复 第二个元素开始判断
	{
		if(a[k] != a[i])
			a[++k] = a[i];		//若不重复,则将k的下一位赋值为a[i]
	}
	return k+1;
}

3.编写递归函数,求两个数x和y的最大公约数。公式递归定义如下:
在这里插入图片描述

#include 
int gcd(int x, int y)
{
	if(y == 0)
		return x;
	return gcd(y,x % y);
}

4.给定图1所示的存储学生信息的结构体数组(每个结构体包含3个字段:姓名、性别、成绩),编写函数,将指定文件in.txt中所有男学生信息存储到该结构体数组中。
(假定文件中存储信息与结构体信息格式相应)

在这里插入图片描述

#include 
#include 
struct student{
	char name[30];
	bool sex;
	int score;
};
int save(struct student st[])
{
	FILE* fp;
	if((fp = fopen("\in.txt","r")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);	
	}
	int i = 0;
	while(!feof(fp))
	{
		fscanf(fp,"%s %d %d",st[i].name, &(st[i].sex),&(st[i].score));
		if(st[i].sex)	//判断是否为男性
			i++;
	}
	fclose(fp);
	return i;
}

5.给定图2所示的单链表,(每个结点包含2个字段:整数信息、后继指针),编写函数删除该单链表中整数信息为奇数的结点。
例如:若单链表中存储的整数信息依次为1、5、6、3、6、0、0、5、2、1,则处理后的链表中存储的key值依次为6、6、0、0、2。

#include 
#include 
struct LinkNode{
	int key;			
	struct LinkNode* next;
};
struct LinkNode* delodd(struct LinkNode* head)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode *p = head, *pre = dummyhead;
	while(p != NULL)
	{
		if(p -> key  % 2 != 0)
			pre -> next = p -> next;
		else
			pre = p;
		p = p -> next;
	}
	return dummyhead -> next;
}

2012级B卷

1.编写函数,输出任意正整数n的位数(n默认为存储十进制的整形变量)
例如:正整数13,则输出2,;正整数3088,则输出4

#include 
int f(int n)
{   int count = 0;
	while(n != 0)
	{
		count++;
		n /= 10;
	}
	return count;
}

2.编写函数,对给定的有序整数数组进行整理,使得所有整数重复2次出现。
例如:原数组为-2、-1、-1、0、0、1、4、4、4则处理后的结果为-2、-2、-1、-1、-1、-1、0、0、0、0、1、1、4、4、4、4、4、4。

算法思想:对数组的每个数字进行遍历时,将所有元素向后移动一个单位,同时将该数组前一个单位复制为该数字,执行完毕后,每次均需要隔一个隔元素执行一次(因为前一个数字是复制过的)

#include 
void f(int a[], int n)
{   
	for(int i = 0; i < 2 * n; i += 2)	 
	{
		for(int j = n + i; j > i; j--)
			a[j] = a[j - 1];
	}
}

也可选择以下方法,先复制到数组的后面,然后排序(题目为有序数组,若条件更改则不能采用此方法)

#include 
void insertsort(int a[], int n)
{
	int i, j;
	for(i = 1; i < n; i++)
	{
		int temp = a[i];
		for(j = i - 1; j >= 0 && a[j] > temp; j--)
			a[j + 1] = a[j];
		a[j + 1] = temp;
	}
}
void selectsort(int a[], int n)
{
	for(int i = 0; i < n-1; i++)
	{
		int min = i;
		for(int j = i + 1; j < n; j++)
			if(a[j] < a[min])
				min = j;
		int temp = a[i];
		a[i] = a[min];
		a[min] = temp;
	}
}
void bubblesort(int a[], int n)
{
	for(int i = n-1; i > 0; i--)
	{
		bool ischange = false;
		for(int j = 0; j < i; j++)
			if(a[j] > a[j+1])
			{
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
				ischange = true;
			}
		if(!ischange)
			break;	
	}
 } 
void f(int a[], int n)
{   
	for(int i = 0, j = n; i < n; i++, j++)	 
		a[j] = a[i];
	sort(a,2*n);
}

3.编写递归函数,求任意正整数n从右边开始的第j位数字(默认,最右侧位第一位)。
公式递归定义如下

在这里插入图片描述

#include 
int digit(int n, int j)
{
	if(j == 1)
		return n % 10;
	return digit(n / 10,j - 1);
}

4.构造图1所示的存储学生信息的结构体数组(每个结构体包含3个字段:姓名、性别、成绩),编写函数,将结构体数组中前M个成绩为优秀的学生信息存储到指定文件out.txt中。
在这里插入图片描述

#include 
#include 
struct student{
	char name[30];
	bool sex;
	int score;
};
void save(struct student st[], int n, int M)
{
	FILE* fp;
	if((fp = fopen("D:\\out.txt","w")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);	
	}
	int count = 0;
	for(int i = 0; i < n && count < M; i++)
	{
		if(st[i].score >= 90)
		{
			fprintf(fp,"%s %d %d\n",st[i].name, st[i].sex,st[i].score);
			count++;	
		}		
	}
	fclose(fp);
}

5.构造图2所示的单链表(每个结点包含2个字段:整数信息、后续指针),编写函数,从单链表的头结点依次处理每个结点,仅保留整数信息大于当前前驱结点的整数信息的结点,使得处理后的单链表中整数信息满足递增顺序。

例如:若单链表中存储的整数信息依次为1、5、6、3、7、7、0、5、8、1,则处理后得到的单链表中存储的整数信息依次为1、5、6、7、8(处理过程:在保留了1、5、6之后,3由于小于之前保留的6而舍弃,之后保留第一个7,第二个7由于等于之前保留的7而舍弃,0和第二个5由于小于之前保留的7而舍弃,之后保留8,第二个1由于小于之前保留的8而舍弃)

#include 
#include 
struct LinkNode{
	int key;			
	struct LinkNode* next;
};
void del(struct LinkNode* head)
{	
	if(head == NULL)
		return;
	struct LinkNode *p = head -> next, *pre = head;
	while(p != NULL)
	{
		if(p -> key <= pre -> key)
			pre -> next = p -> next;
		else
			pre = p;
		p = p -> next;
	}
}

2011级A卷

1.编写函数,判定正整数m和n(均至少为2)是否满足:数m为数n可分解的最小质因数(数n可分解的最小质因数为整除n的最小质数)
//提示:判定m为质数且m是n的最小因数

#include 
bool isMinPrime(int m, int n)
{
	for(int i = 2; i < m; i++)
	{
		if(m % i == 0 || n % i == 0)//若m为非质数或在m之前出现了n的最小质因数则返回false 
			return false;
	}
	if(n % m != 0)	//判断m是否为n的质因数 
		return false;
	return true;
}

2.编写函数,对给定的整数数组a的前n个元素排序,使得所有正整数均出现在负整数和零之前。
//提示:排序结果中,正整数之间的出现顺序不受限制,负整数和0之间的出现顺序不限制。
例如:
原数组为-1、4、-3、0、2、1、-9、7,则排序后可以为4、2、1、7、0、-1、-3、-9

算法答案分为两个版本,第一版为冒泡排序的变式,重点是不改变元素相对顺序,因而采用了o(n2)的冒泡排序算法
将非正元素下沉,然后记录第一个非正元素的位置,再对负元素和0元素再进行一次下沉
第二个版本为答案上的版本,会改变相对顺序的快速排序

#include 
void sort(int a[], int n)	
{
	int pos = -1;					
	//pos用于记录最后一个小于等于0的元素的下标,初始化为-1 
	for(int i = n - 1; i > 0; i--)	//第一次排序,将所有非整数放在正数的后面 
		for(int j = 0; j < i; j++)
		{
			if(a[j] <= 0)
			{
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
				pos = j + 1;
			}
		}
	if(pos == -1)	//若未出现非负值则直接返回
		return; 
	for(int i = n - 1; i > pos; i--)	//第二次排序,将所有0放在负数的后面 
		for(int j = pos; j < i; j++)
		{
			if(a[j] < 0)
			{
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
}
#include 
void sort(int a[], int n)
{
	int left = 0, right = n - 1;
	while(left < right)
	{
		while(left < right && a[left] > 0)		left++;
		while(left < right && a[right] <= 0)	right--;
		if(left < right)
		{
			int temp = a[left];
			a[left] = a[right];
			a[right] = temp;
		}
	}
}

3.编写递归函数,实现按照如下公式计算的功能。
//提示:如果独立编写阶乘运算函数,可以不考虑存储溢出,默认结果类型为整型。

在这里插入图片描述
其中n为自然数。

方法1#include 
int fac(int n)
{
	if(n == 1)	return 1;
	return n * fac(n-1);
}
double f(int n)
{
	if(n == 0)
		return 0;
	return 1.0 * n / ((n+1) * fac(n+2)) + f(n - 1);
}
方法2double f(int n)
{
	if(n == 0)
		return 0;
	int temp = 1;
	for(int i = 1; i <= n + 2; i++)
		temp *= i;
	return 1.0 * n / ((n+1) * (temp)) + f(n - 1);
}

4.定义一个表示学生的结构体(包含3个字段:姓名、性别、成绩),编写函数,将下图所示的结构体数组s中的前n个学生的信息,存储到当前目录下的output.txt中。
//提示:性别可以定义为bool、int、enum等类型均可,存储信息的具体形式不限制
在这里插入图片描述
例如:一个学生的信息为Zhangsan、true、83,另一个学生的信息为LiSi、false、76。

#include 
struct student{
	char name[30];	//姓名
	bool sex;		//性别
	int score;		//分数
};
void save(struct student st[], int n)
{
	FILE* fp;
	if((fp = fopen("out.txt","w")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);	
	}
	for(int i = 0; i < n; i++)
	{
		fprintf(fp,"%s %d %d\n",st[i].name, st[i].sex,st[i].score);		
	}
	fclose(fp);
}

5.定义一个单链表(每个结点包含2个字段:整数信息、后继指针),如下图所示。编写函数,删除该单链表中所含整数信息等于x的多个重复结点。
例如:若单链表中存储的整数信息依次是1、5、5、0、5、6、0、0、5、1,如果x为5,则得到的单链表中相应信息依次是1、0、6、0、0、1。

#include 
#include 
struct LinkNode{
	int key;			
	struct LinkNode* next;
};
void del(struct LinkNode* head, int x)
{	
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode *p = head, *pre = dummyhead;
	while(p != NULL)
	{
		if(p -> key == x)
			pre -> next = p -> next;
		else
			pre = p;
		p = p -> next;
	}
}

2011级B卷

1.编写函数,实现按照如下公式计算的功能。
在这里插入图片描述
其中n为自然数。

答案参看2011级A卷第3题

2.编写函数,对给定的整数数组a(数组长度和元素个数均为N)进行判定:是否存在某个整数a[i](0

答案参看2016级B卷第2题

3.编写一个递归函数,计算给定正整数的所有组成数字之和
例如:给定参数为105,则返回结果应该为6(通过1+0+5=6获得)

答案参看2016级B卷第3题

4.构造一个表示教师的结构体(包含三个字段,姓名,性别,年龄),编写函数,读入M个教师的信息,存入一个结构体数组中,如下图所示:
在这里插入图片描述
例如:一个教师的信息为Zhangsan、true、50,另一个教师的信息为Lisi、false、37。

答案参看2016级B卷第4题

五、设有一个保存教师信息的单链表,(每个结点包含四个字段:姓名,性别,年龄,后继指针),构造该链表中一节的数据类型声明:编写函数,在给定链表上查找所有女教师的信息,并存储到指定文件output.txt中。

答案参看2016级B卷第5题

2010级A卷

1.编写函数,按照如下公式计算圆周率π的值(精确到1e-5)
在这里插入图片描述
答案参看 2015级唐班B卷

2.编写程序,由键盘输入一个字符串(仅包括数字字符、英文字符和空格),把该字符串中英文字符和空格过滤掉,提取所有整数,并将得到的整数序列输出到文件int.txt中。例如:输入字符串为:12A34 567Bc89D,则得到的整数序列为12 34 567 89

#include 
#include 
int main()
{
	FILE *fp;
	if((fp = fopen("D:\\int.txt","w")) == NULL)
	{
		printf("can not open the file\n");
		exit(0);
	}
	char str[30];
	scanf("%s",str);
	int i = 0;
	while(str[i] != '\0')
	{
		if(str[i] <= '0' || str[i] >= '9')
			str[i] = ' ';
			
			i++;
	}
	fprintf(fp,"%s",str);	//cichu此处可替换为fputs(str,fp);
	fclose(fp);
	return 0;
}

3.编写程序,打印一个n行n列矩阵中所有满足下面条件的元素aij;
1)aij是第i行中所有元素的最大值;
2)如果将第j列中所有元素a1j,a2j,…anj按照从小到大的顺序排序,aij为第j/2个元素(最小元素为第0个元素,j/2为整数除法)。

#include 
int main()
{
	int n;
	printf("请输入矩阵的行列数\n");
	scanf("%d", &n);
	int a[10][10];
	printf("请输入二维矩阵元素\n");
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
			scanf("%d", &a[i][j]);
	}
	for (int i = 0; i < n; i++)
	{
		int j = 0;					//第i行中最大值的下标
		for (int k = 0; k < n; k++)		//寻找第i行中最大值
			if (a[i][j] < a[i][k])
				j = k;
		int count = 0;					//设置count计数器用于计算第j列中有多少个元素小于该最大值
		for (int k = 0; k < n; k++)
			if (a[k][j] < a[i][j])
				count++;
		if (count == n / 2)
			printf("%d ", a[i][j]);
	}
	return 0;
}

4.每个学生的信息卡片包括学号、姓名和性别三项。编写程序,由键盘依次输入n个学生的信息,创建一个用于管理学生信息的单链表,如下图所示(必须说明单链表中每个结点的数据结构定义),并在该单链表中添加一个给定结点x。
5.编写程序,在上述建立的单链表中删除所有学号为z的结点(学号为z的结点可能有多个。)

#include 
#include 
struct LinkNode{
	int num;		//学号
	char name[30];	//姓名 
	int sex;		//性别,男为1,女为0
	struct LinkNode *next;
};
struct LinkNode* creat(int n)
{
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* rear = head;
	for(int i = 0; i < n; i++)
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		printf("请输入学生的学号、姓名、性别\n");
		scanf("%d %s %d",&(p->num),p->name,&(p->sex));
		p -> next = rear -> next;
		rear -> next = p;
		rear = p;
	}
	return head -> next;
}
void insert(struct LinkNode* head)	//本算法用于将结点插入到链表的末尾 
{
	if(head == NULL)
	{
		return;
	}
	struct LinkNode* p = head;
	while(p -> next != NULL)
		p = p -> next;
	struct LinkNode* q = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	printf("请输入需要添加的学生信息\n");
	scanf("%d %s %d",&(q->num),q->name,&(q->sex));
	q -> next = p -> next;
	p -> next = q;
}
struct LinkNode* del(struct LinkNode* head, int z)
{
	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = head;
	struct LinkNode *p = head, *pre = dummyhead;
	while(p != NULL)
	{
		if(p -> num == z)
			pre -> next = p -> next;
		else
			pre = p;
		p = p -> next;
	}
	return dummyhead -> next;
} 
int main()
{
	int n, z;
	printf("请输入需要录入信息的学生人数\n");
	scanf("%d",&n);
	struct LinkNode* head = creat(n);
	insert(head);
	printf("请输入需要删除信息的学生学号\n");
	scanf("%d",&z);
	head = del(head, z);
	return 0;
}

2010级B卷

1.编写程序根据如下公式计算X的值(精确到1e-5)。
在这里插入图片描述

#include 
int main()
{
    int i = 1;
    double taylor = 1 / (1.0 * (2 * i - 1)) * (1.0 * (2 * i) ) / (2 * i - 1);	
    //求出每一项的值
    double sum = 0;
    while(taylor > 1e-5)
    {
        sum += taylor;
        i++;
        taylor = 1 / (1.0 * (2 * i - 1)) * (1.0 * (2 * i) ) / (2 * i - 1);	
        //更新taylor
    }
    printf("%lf",sum);
    return 0;
}

2.编写程序,输出一个n行n列矩阵中所有鞍点aij,即元素aij满足下列条件:
1)aij是第i行中所有元素的最小值
2)aij是第j列中所有元素的最大值

#include 
int main()
{
	int n;
	printf("请输入矩阵的行列数\n");
	scanf("%d",&n);
	int a[n][n];
	printf("请输入二维矩阵元素\n");
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
			scanf("%d",&a[i][j]); 
	}
	int count = 0;
	for(int i = 0; i < n; i++)	
		for(int j = 0; j < n; j++)
		{
			bool max = true, min = true;	//先假定该位置元素是行最小,列最大 
			for(int k = 0; k < n; k++)		//先判断是否为行最小 
				if(a[i][k] < a[i][j])
					min = false;
			for(int k = 0; k < n; k++)		//再判断是否为列最大 
				if(a[k][j] > a[i][j])
					max = false;
			if(max && min)
			{
				printf("%d为鞍点\n",a[i][j]);
				count++;
			}
		} 
	if(count == 0)
		printf("None\n");
	return 0;
}

4.编写程序,将一个单链表转换为一个反向的单链表。

算法思想:递归
1.若头结点为空,直接返回头结点 
2.reverse (head -> next)的返回值为新头结点,将后继结点的后继指向该结点,该结点后继置为空
3.递归边界为当前结点的下一个结点为空,则当前结点即为最后一个头结点,无需再次递归寻找头结点 
struct LinkNode* reverse1(struct LinkNode* head)
{
	if(head == NULL || head -> next == NULL)
		return head;
	struct LinkNode* p = reverse(head -> next);
	head -> next  -> next = head;
	head -> next = NULL;
	return p;
}
struct LinkNode* reverse2(struct LinkNode* head)
{

	struct LinkNode* dummyhead = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	dummyhead -> next = NULL;
	while(head != NULL)
	{
		struct LinkNode* temp = head -> next;
		head -> next = dummyhead -> next;
		dummyhead -> next = head;
		head = temp;
	}
	return dummyhead -> next;
}

5.每个教师的信息卡片包括教工号、姓名、职称和学院名称三项,编写程序,由键盘依次输入n个教师的信息,创建一个用于管理教师信息的单链表,如下图所示(必须说明该单链表中每个结点的数据类型定义);并保证添加完所有信息后,该单链表按照教工号从小到大排序。

#include 
#include 
struct LinkNode{
	int num;		//工号
	char name[30];	//姓名 
	char PI[30];	//职称和学院名称 
	struct LinkNode *next;
};
struct LinkNode* creat(int n)
{
	struct LinkNode* head = (struct LinkNode*)malloc(sizeof(struct LinkNode));
	head -> next = NULL;
	struct LinkNode* pre = head;
	for(int i = 0; i < n; i++)
	{
		struct LinkNode* p = (struct LinkNode*)malloc(sizeof(struct LinkNode));
		printf("请输入教师的工号、姓名、职称和学院名\n");
		scanf("%d %s %s",&(p->num),p->name,p->PI);
		while(pre -> next != NULL && pre -> next -> num < p -> num)
			pre = pre -> next;
		p -> next = pre -> next;
		pre -> next = p;
		pre = head;
	}
	return head -> next;
}
int main()
{
	int n;
	printf("请输入需要录入教师信息的人数\n");
	scanf("%d",&n);
	struct LinkNode* head = creat(n);
	return 0;
}

你可能感兴趣的:(吉林大学考研,数据结构,c语言,程序设计)