6-1 | 计算两数的和与差 |
6-2 | 利用指针找最大值 |
6-3 | 在数组中查找指定元素 |
6-4 | 使用函数的选择法排序 |
6-5 | 判断回文字符串 |
6-6 | 数组循环右移 |
6-7 | 拆分实数的整数与小数部分 |
6-8 | 分类统计各类字符个数 |
7-1 | 冒泡法排序 |
7-2 | 猴子选大王 |
7-3 | 组合数的和 |
6-1 计算两数的和与差
本题要求实现一个计算输入的两数的和与差的简单函数。
函数接口定义:
void sum_diff( float op1, float op2, float *psum, float *pdiff );
其中op1
和op2
是输入的两个实数,*psum
和*pdiff
是计算得出的和与差。
void sum_diff(float op1, float op2, float *psum, float *pdiff)
{
*psum = op1 + op2;
*pdiff = op1 - op2;
}
6-2 利用指针找最大值
本题要求实现一个简单函数,找出两个数中的最大值。
函数接口定义:
void findmax( int *px, int *py, int *pmax );
其中px
和px
是用户传入的两个整数的指针。函数findmax
应找出两个指针所指向的整数中的最大值,存放在pmax
指向的位置。
void findmax(int *px, int *py, int *pmax)
{
if(*px > *py) *pmax = *px;
else *pmax = *py;
}
6-3 在数组中查找指定元素
本题要求实现一个在数组中查找指定元素的简单函数。
函数接口定义:
int search( int list[], int n, int x );
其中list[]
是用户传入的数组;n
(≥0)是list[]
中元素的个数;x
是待查找的元素。如果找到
则函数search
返回相应元素的最小下标(下标从0开始),否则返回−1。
int search(int list[], int n, int x)
{
for(int i = 0; i < n; i++)
if(list[i] == x)
return i;
return -1;
}
6-4 使用函数的选择法排序
本题要求实现一个用选择法对整数数组进行简单排序的函数。
函数接口定义:
void sort( int a[], int n );
其中a
是待排序的数组,n
是数组a
中元素的个数。该函数用选择法将数组a
中的元素按升序排列,结果仍然在数组a
中。
解:
刚开始写错了,写了个插入排序,也放进来吧。
void sort(int a[], int n)
{
int cur = 1; // 从第1个数开始(第0个相当于已排序)
while(cur < n)
{
for(int i = 0; i < cur; i++)
if(a[i] > a[cur]) // 在已排序序列中找到比它大的
{
// a[i] 及后边所有数后移一位,然后把 a[cur] 插入在 a[i] 位置
int tmp = a[cur];
for(int j = cur; j > i; j--)
a[j] = a[j - 1];
a[i] = tmp;
break;
}
// 已排序序列中没有比它大的,相当于已经排好序了,不需要处理
++cur;
}
}
下边是重新写的选择排序,每次在未排序序列里选一个最小的,放在已排序序列最后边。
void sort(int a[], int n)
{
if(n == 1) return;
int cur = 0;
while(cur < n)
{
int min_val = a[cur], min_idx = cur;
for(int i = cur + 1; i < n; i++)
if(a[i] < min_val)
{
min_val = a[i];
min_idx = i;
}
// 交换 a[cur] 和 a[min_idx],使得最小的数放到正确的位置
int tmp = a[cur];
a[cur] = min_val;
a[min_idx] = tmp;
++cur;
}
}
6-5 判断回文字符串
本题要求编写函数,判断给定的一串字符是否为“回文”。所谓“回文”是指顺读和倒读都一样的字符串。如“XYZYX”和“xyzzyx”都是回文。
函数接口定义:
bool palindrome( char *s );
函数palindrome
判断输入字符串char *s
是否为回文。若是则返回true
,否则返回false
。
解:
要注意两点:
- 要先以 '\0' 结尾来判断计算出字符串的长度
- 不能对 s 进行 ++ 操作,否则指针指向的元素就变了,需要一个 tmp 指针来遍历 s 字符串。
bool palindrome(char *s)
{
int len = 0;
char *tmp = s;
while(*tmp != '\0')
{
++tmp;
++len;
}
int l = 0, r = len - 1;
while(l < r)
{
if(s[l] != s[r]) return false;
--r;
++l;
}
return true;
}
6-6 数组循环右移
本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a0a1⋯an−1)变换为(an−m⋯an−1a0a1⋯an−m−1)(最后m个数循环移至最前面的m个位置)。
函数接口定义:
int ArrayShift( int a[], int n, int m );
其中a[]
是用户传入的数组;n
是数组的大小;m
是右移的位数。函数ArrayShift
须将循环右移后的数组仍然存在a[]
中。
解:
用一个tmp数组,存需要移到后边的数,分三步完成右移操作即可。
int ArrayShift(int a[], int n, int m) // 返回值没有用到没有意义
{
if(m == 0) return 0;
m = m % n;
int t[m];
for(int i = 0; i < m; i++) // 把 a[n - m] ~ a[n - 1] 存起来
t[i] = a[n - m + i];
for(int i = n - 1; i >= m; i--) // 赋值 a[m] ~ a[n - 1] 为 a[0] ~ a[n - m - 1],但是必须从右往左
a[i] = a[i - m];
for(int i = 0; i < m; i++) // 赋值 a[0] ~ a[m - 1] 为 a[n - m] ~ a[n - 1]
a[i] = t[i];
}
6-7 拆分实数的整数与小数部分
函数接口定义:
void splitfloat( float x, int *intpart, float *fracpart );
其中x
是被拆分的实数(0≤x
<10000),*intpart
和*fracpart
分别是将实数x拆分出来的整数部分与小数部分。
void splitfloat(float x, int *intpart, float *fracpart)
{
*intpart = (int)x;
*fracpart = x - *intpart;
}
6-8 分类统计各类字符个数
本题要求实现一个函数,统计给定字符串中的大写字母、小写字母、空格、数字以及其它字符各有多少。
函数接口定义:
void StringCount( char *s );
其中 char *s
是用户传入的字符串。函数StringCount
须在一行内按照
大写字母个数 小写字母个数 空格个数 数字个数 其它字符个数
的格式输出。
void StringCount(char *s)
{
int upper = 0, lower = 0, number = 0, space = 0, others = 0;
while(*s != '\0')
{
if(*s >= 'A' && *s <= 'Z') ++upper;
else if(*s >= 'a' && *s <= 'z') ++lower;
else if(*s == ' ') ++space;
else if(*s >= '0' && *s <= '9') ++number;
else ++others;
++s;
}
printf("%d %d %d %d %d\n", upper, lower, space, number, others);
}
7-1 冒泡法排序
将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。
本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。
输入格式:
输入在第1行中给出N和K(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。
输出格式:
在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。
输入样例:
6 2
2 3 5 1 6 4
输出样例:
2 1 3 4 5 6
#include <stdio.h>
int main()
{
int n, k;
scanf("%d%d", &n, &k);
int a[n];
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
for(int i = 0; i < k; i++)
for(int j = 0; j < n - i - 1; j++)
if(a[j] > a[j + 1])
{
int tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
printf("%d", a[0]);
for(int i = 1; i < n; i++)
printf(" %d", a[i]);
return 0;
}
7-2 猴子选大王
一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
解:
用纯计算机方法解,不用任何数学公式,就是用一个长度为 n 的数组(全部初始化为1),每遍历3个让当前这个位置的值变为0。报数的时候,只有值为1的位置才能报数,值为0的不能报数即可。
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
if(n == 1)
{
printf("1\n"); // 就一个人的情况
return 0;
}
int a[n];
for(int i = 0; i < n; i++) a[i] = 1;
int remain = n, cur = 0;
while(1)
{
int i = 0;
while(i < 2)
{
if(a[cur] == 1)
++i;
cur = (cur + 1) % n; // 每次报数不能 ++cur,必须 cur = (cur + 1) % n
}
while(a[cur] == 0) cur = (cur + 1) % n;
a[cur] = 0;
--remain;
while(a[cur] == 0) cur = (cur + 1) % n;
if(remain == 1)
{
printf("%d\n", cur + 1);
return 0;
}
}
return 0;
}
7-3 组合数的和
给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字。要求所有可能组合出来的 2 位数字的和。例如给定 2、5、8,则可以组合出:25、28、52、58、82、85,它们的和为330。
输入格式:
输入在第一行中给出 N(1 < N < 10),随后一行给出 N 个不同的非 0 个位数字。数字间以空格分隔。
输出格式:
输出所有可能组合出来的2位数字的和。
#include <stdio.h>
int main()
{
int n,sum = 0;
scanf("%d", &n);
int a[n];
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(i != j)
sum += a[i] * 10 + a[j];
printf("%d\n", sum);
return 0;
}