目录
-
- 开篇说两句
- [1. 水仙花数](#1. 水仙花数)
- [2. 斐波那契数列](#2. 斐波那契数列)
- [3. 猴子吃桃问题](#3. 猴子吃桃问题)
- [4. 物体自由落地](#4. 物体自由落地)
- [5. 矩阵对角线元素之和](#5. 矩阵对角线元素之和)
- [6. 求素数](#6. 求素数)
- [7. 最大公约数和最小公倍数](#7. 最大公约数和最小公倍数)
- [8. 企业发放的奖金根据利润提成](#8. 企业发放的奖金根据利润提成)
- [9. 打印出菱形图案](#9. 打印出菱形图案)
- 10、折半查找
- 11、快速排序
- 12、选择排序法
- 13、冒泡排序法
- 14、归并排序算法
- 15、希尔排序算法
- 结语
开篇说两句
-
亲爱的大学生朋友们,考试季即将来临,C语言期末考试正悄然而至!这是我们程序员的战场,是我们思维的舞台,更是我们梦想的起点。
-
C语言,如同编程世界的起源之星,闪耀着光芒,等待我们去探索。这门语言承载着计算机科学的基石,是我们编程生涯的第一步。期末考试,就像一场挑战,它考验着我们对知识的掌握,更是一个展示自我的舞台。
-
在这个寒冷的冬日,键盘敲击的声音伴随着编程的思路,在计算机实验室里回响。每一行代码都是一次思维的碰撞,每一个函数都是一段知识的体现。或许,这正是我们向往的编程之美。
-
当你看到屏幕上那一行行优美的代码,在程序运行时,控制台上一片整齐的输出,你会感受到一种前所未有的成就感。而这正是C语言的魅力,它不仅是我们通向计算机世界的桥梁,更是我们挑战自我的武器。
-
考试并非是一场简单的应试游戏,而是一个展示自我的机会。在这个过程中,你不仅仅是在考验知识,更是在锻炼解决问题的能力。在代码的海洋里,展翅飞翔,挥洒青春的汗水,为自己的梦想努力奋斗。
-
C语言期末考试,就是我们向梦想进军的战场。让我们携手迎战,用键盘书写属于自己的传奇。不论成绩如何,都要记得,每一次的尝试都是一次收获,每一行代码都是一份努力的证明。
-
愿你们在这场考试中发挥出色,愿你们的代码风格优雅,愿你们在编程的世界里找到自己的坐标。加油吧,年轻的程序员们!用C语言,书写属于你们的辉煌篇章!
-
下面是15道超级经典的题目,请收好
1. 水仙花数
题目描述
水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)。
分析
解题思路很简单,遍历所有3位数,判断每个位上数字的3次幂之和是否等于这个数本身。
代码示例
c
#include <stdio.h>
int main() {
for (int num = 100; num < 1000; num++) {
int digit, sum = 0, temp = num;
while (temp > 0) {
digit = temp % 10;
sum += digit * digit * digit;
temp /= 10;
}
if (sum == num) {
printf("%d is a Narcissistic number.\n", num);
}
}
return 0;
}
2. 斐波那契数列
题目描述
斐波那契数列(Fibonacci sequence)是指每个数字是前两个数字之和。有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
分析
这是一个典型的斐波那契数列问题,每个月的兔子总数等于前两个月兔子总数之和。
代码示例
c
#include <stdio.h>
int fibonacci(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
int main() {
for (int month = 1; month <= 10; month++) {
printf("Month %d: %d pairs of rabbits\n", month, fibonacci(month));
}
return 0;
}
3. 猴子吃桃问题
题目描述
猴子第一天吃了若干个桃子,当即吃了一半,还不解馋,又多吃了一个;第二天,吃剩下的桃子的一半,还不过瘾,又多吃了一个;以后每天都吃前一天剩下的一半多一个,到第10天想再吃时,只剩下一个桃子了。问第一天共吃了多少个桃子?
分析
通过逆推,可以得到第一天的桃子数,每天吃的桃子数是前一天桃子数的一半再加1。
代码示例
c
#include <stdio.h>
int main() {
int total_peaches = 1;
for (int day = 9; day >= 1; day--) {
total_peaches = (total_peaches + 1) * 2;
}
printf("The monkey ate a total of %d peaches on the first day.\n", total_peaches);
return 0;
}
4. 物体自由落地
题目描述
一球从100米高度自由落下,每次落地后反弹回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?
分析
每次下落和反弹可以看作是一个等比数列,总共经过的距离等于所有下落和反弹的距离之和,第10次反弹高度为第9次下落高度的一半。
代码示例
c
#include <stdio.h>
int main() {
double total_distance = 100.0; // 初始高度
double current_height = 100.0; // 当前高度
for (int i = 2; i <= 10; i++) {
current_height /= 2;
total_distance += current_height * 2;
}
printf("Total distance after 10 bounces: %.2f meters\n", total_distance);
printf("Height after 10 bounces: %.2f meters\n", current_height);
return 0;
}
5. 矩阵对角线元素之和
题目描述
求一个3*3矩阵对角线元素之和。
分析
对角线元素包括主对角线和副对角线上的元素,它们的和就是对角线元素之和。
代码示例
c
#include <stdio.h>
int main() {
int matrix[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int sum = 0;
for (int i = 0; i < 3; i++) {
sum += matrix[i][i]; // 主对角线
sum += matrix[i][2 - i]; // 副对角线
}
printf("Sum of diagonal elements: %d\n", sum);
return 0;
}
6. 求素数
题目描述
判断101-200之间有多少个素数,并输出所有素数。
分析
素数是指除了1和自身外没有其他正整数可以整除的数。遍历101到200之间的数字,判断每个数字是否为素数。
代码示例
c
#include <stdio.h>
#include <stdbool.h>
bool is_prime(int num) {
if (
num < 2) {
return false;
}
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
int main() {
int count = 0;
for (int num = 101; num <= 200; num++) {
if (is_prime(num)) {
printf("%d is a prime number.\n", num);
count++;
}
}
printf("Total prime numbers between 101 and 200: %d\n", count);
return 0;
}
7. 最大公约数和最小公倍数
题目描述
输入两个正整数m和n,求其最大公约数和最小公倍数。
分析
最大公约数可以使用辗转相除法求解,最小公倍数等于两数之积除以最大公约数。
代码示例
c
#include <stdio.h>
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b) {
return a * b / gcd(a, b);
}
int main() {
int m, n;
printf("Enter two positive integers: ");
scanf("%d %d", &m, &n);
int greatest_common_divisor = gcd(m, n);
int least_common_multiple = lcm(m, n);
printf("Greatest Common Divisor: %d\n", greatest_common_divisor);
printf("Least Common Multiple: %d\n", least_common_multiple);
return 0;
}
8. 企业发放的奖金根据利润提成
题目描述
企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?
分析
根据利润的不同区间,分别计算不同的提成比例。
代码示例
c
#include <stdio.h>
int main() {
double profit;
printf("Enter the profit for the month: ");
scanf("%lf", &profit);
double bonus = 0.0;
if (profit <= 100000) {
bonus = profit * 0.1;
} else if (profit <= 200000) {
bonus = 100000 * 0.1 + (profit - 100000) * 0.075;
} else if (profit <= 400000) {
bonus = 100000 * 0.1 + 100000 * 0.075 + (profit - 200000) * 0.05;
} else if (profit <= 600000) {
bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + (profit - 400000) * 0.03;
} else if (profit <= 1000000) {
bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + 200000 * 0.03 + (profit - 600000) * 0.015;
} else {
bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + 200000 * 0.03 + 400000 * 0.015 + (profit - 1000000) * 0.01;
}
printf("The bonus for the month is: %.2f\n", bonus);
return 0;
}
9. 打印出菱形图案
题目描述
打印出如下的菱形图案:
*
***
*****
*******
*****
***
*
分析
可以通过嵌套循环实现打印菱形图案,控制空格和星号的输出。
代码示例
c
#include <stdio.h>
int main() {
int rows = 4; // 菱形的行数
// 上半部分
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= rows - i; j++) {
printf(" ");
}
for (int k = 1; k <= 2 * i - 1; k++) {
printf("*");
}
printf("\n");
}
// 下半部分
for (int i = rows - 1; i >= 1; i--) {
for (int j = 1; j <= rows - i; j++) {
printf(" ");
}
for (int k = 1; k <= 2 * i - 1; k++) {
printf("*");
}
printf("\n");
}
return 0;
}
10、折半查找
前提条件
有序的顺序表(需要具有随机访问的特性,链表没有)。
基本思想
搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。折半搜索每次把搜索区域减少一半,时间复杂度为Ο(logn)。
代码示例
c
#include <stdio.h>
int binarySearch(int arr[], int left, int right, int target) {
while (left <= right) {
int mid = left + (right - left) / 2;
// 检查目标是否在中间
if (arr[mid] == target)
return mid;
// 如果目标更大,忽略左半部分
if (arr[mid] < target)
left = mid + 1;
// 如果目标更小,忽略右半部分
else
right = mid - 1;
}
// 如果执行到这里,表示元素未找到
return -1;
}
int main() {
int arr[] = {2, 3, 4, 10, 40};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 10;
int result = binarySearch(arr, 0, n - 1, target);
(result == -1) ? printf("元素不在数组中")
: printf("元素在索引 %d 处", result);
return 0;
}
11、快速排序
算法思想
在待排序表L[1...n]中任取⼀个元素pivot作为枢轴,通过⼀趟排序将待排序表划分为独⽴的两部分L[1...k-1]和L[k+1...n],使得L[1...k-1]中的所有元素⼩于pivot,L[k+1...n]中的所有元素⼤于等于pivot,则pivot放在了其最终位置L(k)上,这个过程称为⼀次"划分"。然后分别递归地对两个⼦表重复上述过程,直⾄每部分内只有⼀个元素或空为⽌,即所有元素放在了其最终位置上。
代码示例
c
#include <stdio.h>
// 交换两个元素
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 将数组划分为两个子数组,小于pivot的在左边,大于的在右边
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选择最右边的元素作为枢轴
int i = low - 1;
for (int j = low; j <= high - 1; j++) {
// 如果当前元素小于等于枢轴,则交换
if (arr[j] <= pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
// 将枢轴放在正确的位置上
swap(&arr[i + 1], &arr[high]);
return i + 1;
}
// 对子数组进行快速排序
void quickSort(int arr[], int low, int high) {
if (low < high) {
// 找到枢轴的位置
int pivotIndex = partition(arr, low, high);
// 分别对两个子数组进行排序
quickSort(arr, low, pivotIndex - 1
);
quickSort(arr, pivotIndex + 1, high);
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
quickSort(arr, 0, n - 1);
printf("\n排序后的数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
12、选择排序法
算法思想
选择排序是一种简单直观的排序算法。基本思想是在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后从剩余未排序元素中继续寻找最小(或最大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
代码示例
c
#include <stdio.h>
// 交换两个元素
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 选择排序函数
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
// 找到未排序序列中最小元素的索引
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex])
minIndex = j;
}
// 将找到的最小元素与未排序序列的第一个元素交换位置
swap(&arr[minIndex], &arr[i]);
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
selectionSort(arr, n);
printf("\n排序后的数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
13、冒泡排序法
算法思想
冒泡排序是一种基本的排序算法,通过多次遍历待排序序列,每次比较相邻的元素,如果顺序不对则交换,经过一轮遍历后,最大的元素会被"浮"到最右边,然后对剩余的元素重复这个过程,直到整个序列有序。
代码示例
c
#include <stdio.h>
// 交换两个元素
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 冒泡排序函数
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
// 如果当前元素比下一个元素大,交换它们
if (arr[j] > arr[j + 1])
swap(&arr[j], &arr[j + 1]);
}
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
bubbleSort(arr, n);
printf("\n排序后的数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
...
注释说明:
swap
函数用于交换两个元素的值。selectionSort
函数实现选择排序算法。bubbleSort
函数实现冒泡排序算法。
14、归并排序算法
算法思想
归并排序采用分治法的思想,将待排序数组分成两个子数组,分别排序,然后合并两个已排序的子数组。归并排序的主要步骤包括分割、排序和合并。
代码示例
c
#include <stdio.h>
#include <stdlib.h>
// 合并两个已排序的子数组
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// 创建临时数组
int L[n1], R[n2];
// 复制数据到临时数组 L[] 和 R[]
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
// 合并临时数组到 arr[l..r]
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
// 复制 L[] 的剩余元素(如果有)
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
// 复制 R[] 的剩余元素(如果有)
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
// 归并排序函数
void mergeSort(int arr[], int l, int r) {
if (l < r) {
// 计算中间位置
int m = l + (r - l) / 2;
// 递归排序左半部分和右半部分
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
// 合并已排序的子数组
merge(arr, l, m, r);
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
mergeSort(arr, 0, n - 1);
printf("\n排序后的数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
15、希尔排序算法
算法思想
希尔排序是插入排序的一种改进版本,也被称为缩小增量排序。希尔排序的基本思想是将整个待排序序列分割成若干个子序列,分别进行直接插入排序,随着增量的逐渐减小,每个子序列的元素越来越多,当增量减小至1时,整个序列恰好被分成一个子序列,此时进行直接插入排序,整个序列就变成有序的。
代码示例
c
#include <stdio.h>
// 希尔排序函数
void shellSort(int arr[], int n) {
// 选择一个增量序列
for (int gap = n / 2; gap > 0; gap /= 2) {
// 对每个子序列进行插入排序
for (int i = gap; i < n; i++) {
int temp = arr[i];
int j;
// 将 arr[j] 插入到正确的位置
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
arr[j] = arr[j - gap];
arr[j] = temp;
}
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
shellSort(arr, n);
printf("\n排序后的数组: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
结语
在程序设计的学习过程中,我们深入探讨了一系列经典的C语言程序设计题目,涵盖了折半查找、快速排序、选择排序、冒泡排序、归并排序、希尔排序等多个算法。通过这些题目,我们锻炼了逻辑思维、代码实现能力,提升了对数据结构和算法的理解。
编程世界犹如一座大学,每一个程序员都是这座大学中的一名学子。而这些经典题目,则是大学课程中的经典教材。通过不断解题,我们犹如在大学校园中行走,探寻知识的奥妙。
在这个过程中,我们不仅仅是在解决问题,更是在挑战自己的思维极限,提升自己的解决问题的能力。每一行代码都是知识的砖瓦,每一个bug都是思维的障碍,而每一次成功的运行,则是知识在大脑中的巧妙拼接。
与此同时,C语言作为程序设计的入门语言,承载着程序员的最初梦想。它犹如大学里的第一门专业课,引领着我们步入编程的殿堂。通过解决这些题目,我们慢慢洞察了编程的奥妙,感受到了代码的魅力。
希望大家在这段程序设计的旅途中,能够坚持不懈,保持对知识的渴望,像追求梦想一样坚定地走下去。无论是遇到怎样的困难,都要学会从中汲取力量,因为在编程的世界里,每一次挑战都是一次成长。
让我们怀揣着对代码的热爱,继续探索编程的海洋,相信在未来的某一天,我们都能够成为自己心中那位优秀的程序员。阅读代码,解决问题,这或许就是我们大学编程之旅的真谛。不忘初心,方得始终。加油,年轻的程序员们!