├── 2-3-4树算法 └── 2-3-4.c ├── B*树算法 ├── README.md ├── btree.cc ├── btree.h ├── btree.tar.gz ├── btree_main.cc ├── fplan.cc ├── fplan.h ├── makefile ├── sa.cc └── sa.h ├── B+树算法 └── btree.c ├── B树算法 └── b_tree.c ├── KMP算法 └── kmp.c ├── LSM树算法 └── LSM.c ├── README.md ├── RSA加密算法 └── rsa.c ├── 三色棋 └── hree-Color_Flag.c ├── 三角矩阵 └── 三角矩阵.c ├── 乱数排列 └── 乱数排列.c ├── 二分搜寻法 └── 二分搜寻法.c ├── 二分查找算法 └── BinarySearch.c ├── 二叉堆 ├── binheap.c ├── binheap.h ├── fatal.h └── main.c ├── 二叉查找树算法 └── BST.c ├── 二叉树排序 └── binary_tree_sort.c ├── 二叉树算法 ├── BinaryTree.c └── README.md ├── 二项堆 ├── binomial_heap.c ├── binomial_heap.h └── main.c ├── 产生可能的集合 └── 产生可能的集合.c ├── 伸展树算法 ├── README.md ├── splay_tree.c └── splay_tree.h ├── 八枚银币 └── 八枚银币.c ├── 八皇后 └── 八皇后.c ├── 冒泡排序算法 ├── BubbleSortMain.c └── README.md ├── 决策树 └── id3.c ├── 分块查找 └── 分块查找.c ├── 分治算法 └── 分治算法.c ├── 剪枝算法 └── 剪枝算法.c ├── 动态栈 └── 动态栈.c ├── 动态规划算法 └── 最大子段和问题的动态规划算法.c ├── 单链表算法 ├── LinkList.c └── README.md ├── 双向链表算法 ├── DoubleList.c └── README.md ├── 后序式 └── 后序式.c ├── 哈夫曼树算法 └── huffman_tree.c ├── 哈希查找 └── 哈希查找.c ├── 回溯算法 └── 回溯算法.cpp ├── 图 ├── 完全图 │ └── 完全图.c ├── 带权图 │ └── 带权图.cpp ├── 无向图 │ └── 无向图.c ├── 无权图 │ └── 无权图.c └── 有向图 │ └── 有向图.c ├── 基数排序算法 └── DigitSort.c ├── 堆排序算法 └── heap_sort.c ├── 多维矩阵转一维矩阵 └── 多维矩阵转一维矩阵.c ├── 大数运算 └── 大数运算.c ├── 完全二叉树算法 └── CBT.c ├── 完美数 └── 完美数.c ├── 宽度优先搜索 └── 宽度优先搜索.c ├── 对称矩阵 └── 对称矩阵.c ├── 对角矩阵 └── 对角矩阵.c ├── 左倾堆 ├── leftist.c ├── leftist.h └── leftist_test.c ├── 布隆过滤器 └── bloom.c ├── 希尔排序算法 ├── README.md └── ShellSort.c ├── 平衡二叉树算法 ├── AVLtree.c └── README.md ├── 并查集 ├── README.md └── 并查集.c ├── 广义表 └── 广义表.c ├── 广度优先搜索 └── 广度优先搜索.c ├── 开源项目 ├── 2048游戏 │ └── game_2048.c ├── 21点游戏 │ └── game.c ├── MiGo开源掌机 │ └── README.md ├── README.md ├── game-of-life │ ├── Makefile │ ├── README.md │ └── lifegen.c ├── snake_game │ ├── main.c │ ├── snake.c │ └── snake.h ├── 中国象棋 │ ├── chess.in │ ├── game.c │ └── load_word.in ├── 五子棋 │ ├── game01.c │ └── game02.c ├── 井字棋 │ └── game.c ├── 俄罗斯方块 │ └── game.c ├── 弹弹乐 │ └── README.md ├── 弹球游戏 │ ├── game.c │ └── game.h ├── 成语接龙 │ ├── getopt.c │ ├── getopt.h │ ├── main.c │ └── tailor.h ├── 打砖块游戏 │ └── game.c ├── 打飞机游戏 │ └── game.c ├── 扫雷游戏 │ ├── main.c │ ├── minesweeper.c │ └── minesweeper.h ├── 推箱子 │ └── boxgame.c ├── 文字冒险游戏 │ └── game.c ├── 猜拳游戏 │ └── game.c ├── 猜数游戏 │ └── game.c ├── 皇帝和后宫 │ └── game.c ├── 老虎机游戏 │ └── game.c ├── 记忆游戏 │ └── game.c ├── 贪吃蛇(穿墙) │ └── game.c └── 贪吃蛇 │ └── game.c ├── 归并排序算法 └── mergesort.c ├── 得分排行 └── 得分排行.c ├── 循序搜寻法 └── 循序搜寻法.c ├── 循环搜寻法 └── 循序搜寻法.c ├── 循环链表算法 ├── README.md └── list_xzy.c ├── 循环队列 └── 循环队列.c ├── 快速排序2 └── 快速排序法(2).c ├── 快速排序3 └── 快速排序法(3).c ├── 快速排序算法 └── quick_sort.c ├── 拓扑排序算法 └── 拓扑排序.c ├── 排列组合 └── 排列组合.c ├── 推荐算法 ├── 协同过滤推荐算法 │ └── 协同过滤推荐算法.java ├── 基于内容的推荐算法 │ ├── Job1.Java │ ├── Job2.java │ ├── Job3.java │ └── Job4.java ├── 流行度推荐算法 │ └── 流行度推荐算法.java └── 混合推荐算法 │ └── 混合推荐算法.c ├── 插值查找 └── 插值查找.c ├── 插入排序算法 ├── InsertSort.c └── README.md ├── 插补搜寻法 └── 插补搜寻法.c ├── 数字拆解 └── 数字拆解.c ├── 数组列优先顺序 └── 列优先.c ├── 数组行优先顺序 └── 行优先.c ├── 斐波那契堆 ├── fibonacci_heap.c ├── fibonacci_heap.h └── main.c ├── 斐波那契查找 └── 斐波那契查找.c ├── 斜堆 ├── skewheap.c ├── skewheap.h └── skewheap_test.c ├── 最大m子段问题 └── 最大m子段问题.c ├── 最大子段和问题的简单算法 └── 最大子段和问题的简单算法.c ├── 最大访客数 └── 最大访客数.c ├── 最小生成树 ├── Kruskal.c └── Prime.c ├── 最短路径算法 └── 最短路径算法.c ├── 最长公共子序列问题 └── 最长公共子序列问题.c ├── 朴素贝叶斯算法 └── 贝叶斯.c ├── 树表查找 ├── biTree.c ├── biTree.h └── main.c ├── 格雷码 └── 格雷码.c ├── 桶排序 └── bin_sort_main.c ├── 模拟退火算法 └── 模拟退火算法.c ├── 河内之塔 └── Hanoi.c ├── 深度优先搜索 └── 深度优先搜索.c ├── 游戏 ├── Tennis │ └── README.md ├── 忍者神龟 │ └── README.md ├── 超级玛丽 │ └── README.md └── 魂斗罗 │ └── README.md ├── 滑动窗口算法 └── 滑动窗口.c ├── 爬山算法 └── 爬山算法.c ├── 生命游戏 └── 生命游戏.c ├── 矩阵连乘 ├── 动态规划迭代实现.java └── 备忘录递归实现.c ├── 稀疏矩阵 └── 稀疏矩阵.c ├── 筛选求质数 └── Eratosthenes.c ├── 红黑树算法 ├── rbtree-tst.c ├── rbtree.c ├── rbtree.h └── xrbtree.c ├── 约束满足搜索 └── 约束满足搜索.c ├── 线性查找 └── 线性查找.c ├── 经典项目 ├── 24点问题.c ├── README.md ├── “抢30”游戏.c ├── 三色球问题.c ├── 个人所得税问题.c ├── 人机猜数问题.c ├── 借书方案知多少.c ├── 兔子产子问题.c ├── 兔子生兔子的问题.c ├── 农夫过河.c ├── 出售金鱼问题.c ├── 分别用递归法和迭代法求阶乘.c ├── 分糖果问题.c ├── 列出真分数序列.c ├── 删除字符数组中特定的字符.c ├── 删除星号.c ├── 判断一个数是否是素数.c ├── 判断回文字符串.c ├── 动态分配数组大小.c ├── 动态数组的实现.c ├── 向文件写入内容并读取显示.c ├── 在字符串的指定位置插入字符.c ├── 奶牛生子的问题.c ├── 委派任务问题.c ├── 存钱问题.c ├── 定时关机小程序.c ├── 定时关机程序.c ├── 实现动态数组,克服静态数组大小固定的缺陷.c ├── 实现文本搜索,类似软件中常用的搜索功能.c ├── 实现的猜拳游戏(剪子锤子布).c ├── 将一个正整数分解质因数.c ├── 将字符串转换为整数.c ├── 将真分数分解为埃及分数.c ├── 常胜将军问题.c ├── 平分7筐鱼.c ├── 打印杨辉三角.c ├── 打鱼还是晒网问题.c ├── 找到一个数的所有真因子.c ├── 抓交通肇事犯问题.c ├── 换分币问题.c ├── 掷骰子游戏.c ├── 搬山游戏.c ├── 数制转换.c ├── 数组旋转问题.c ├── 文本文件复制代码.c ├── 新娘和新郎问题.c ├── 新郎和新娘问题.c ├── 旅客国籍问题.c ├── 最佳存款方案.c ├── 歌星大奖赛.c ├── 比较两个分数的大小.c ├── 水仙花数.c ├── 求nt的值(3种方法).c ├── 求不重复的3位数.c ├── 求亲密数.c ├── 求勾股数.c ├── 求回文数.c ├── 求回文素数.c ├── 求多项式之和.c ├── 求孪生素数.c ├── 求完数.c ├── 求最大公约数.c ├── 求最小公倍数.c ├── 求某一年的某一月有多少天问题.c ├── 求梅森素数.c ├── 求给定范围内的所有素数.c ├── 求自守数.c ├── 求车速.c ├── 求高次方数的尾数.c ├── 求黑洞数.c ├── 爱因斯坦的数学题.c ├── 牛顿迭代法求方程根.c ├── 狼追兔子.c ├── 猜牌术.c ├── 猴子吃桃问题.c ├── 百钱百鸡问题.c ├── 矩阵转置.c ├── 线性同余法产生随机数.c ├── 统计文件中单词的个数.c ├── 统计文件中的字符数、单词数以及总行数.c ├── 统计英文字母、空格、数字和其它字符的数目.c ├── 统计输入的字符串的长度.c ├── 自动发牌程序.c ├── 舍罕王的失算.c ├── 获取开机时间.c ├── 要发就发(1898)问题.c ├── 计算一个数的平方根.c ├── 计算你收藏的硬币值多少钱.c ├── 计算分数的精确值.c ├── 计算厄密多项式.c ├── 计算用1分钱、2分钱、5分钱组成1元钱的方式.c ├── 谁在说谎问题.c ├── 谁家孩子跑的最慢问题.c ├── 谁是窃贼问题.c ├── 谜语博士的难题.c ├── 输入一行数据并统计其长度.c ├── 输出2的N次幂.c ├── 输出菱形.c ├── 选美比赛.c ├── 递归解决分鱼问题.c ├── 递归解决年龄问题.c ├── 邮票组合.c ├── 马克思手稿中的数学题.c ├── 马踏棋盘.c ├── 验证哥德巴赫猜想.c ├── 魔方阵.c ├── 黑与白问题.c └── 黑白子交换.c ├── 老鼠走迷宫1 └── 老鼠走迷官(1).c ├── 老鼠走迷宫2 └── 老鼠走迷官(2).c ├── 背包问题 └── Knapsack Problem.c ├── 视频讲解游戏 ├── 太空大战 │ └── SpaceGame.rar ├── 奇怪大冒险 │ └── Adventure.rar ├── 气球塔防 │ └── BalloonDefense.rar ├── 火柴人试炼之地 │ └── Matchman.rar └── 雷霆战机 │ └── ThunderFighter.rar ├── 计数排序算法 └── CountSort.c ├── 贪心算法 └── greedy.c ├── 费列数列 └── Fibonacci.c ├── 费氏搜寻法 └── 费氏搜寻法.c ├── 资料 ├── README.md └── 数据结构1800题(含详解答案).pdf ├── 迭代加深搜索 └── 迭代加深搜索.cpp ├── 选择排序算法 ├── README.md └── selectsort.c ├── 递归算法 └── 递归算法.c ├── 邻接矩阵 └── 邻接矩阵.c ├── 重叠子问题的递归最优解 └── 重叠子问题的递归最优解.c ├── 链式队列 └── 链式队列.c ├── 长PI └── 长PI.c ├── 阿姆斯壮数 └── 阿姆斯壮数.c ├── 静态栈 └── 静态栈.c ├── 顺序查找 └── 顺序查找.c ├── 顺序队列 └── 顺序队列.c ├── 骑士走棋盘 └── Knight_tour.c ├── 魔方阵1 └── 魔方阵(1).c ├── 魔方阵2 └── 魔方阵(2).c └── 魔方阵3 └── 魔方阵(3).c /B*树算法/README.md: -------------------------------------------------------------------------------- 1 | # B\*树 2 | 3 | 是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
4 | 5 | B\*树定义了非叶子结点关键字个数至少为(2/3)\*M,即块的最低使用率为2/3
6 | 7 | (代替B+树的1/2);
8 | 9 | B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据
10 | 11 | 复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父
12 | 13 | 结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针;
14 | 15 | B\*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分
16 | 17 | 数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字
18 | 19 | (因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之
20 | 21 | 间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针;
22 | 23 | 所以,B\*树分配新结点的概率比B+树要低,空间使用率更高;
24 | 25 | ![image](https://user-images.githubusercontent.com/87458342/129178572-308bc62b-78b1-44bb-b58a-73cafd82e997.png) 26 | 27 | -------------------------------------------------------------------------------- /B*树算法/btree.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/B*树算法/btree.tar.gz -------------------------------------------------------------------------------- /B*树算法/makefile: -------------------------------------------------------------------------------- 1 | #Project: B*-tree based floorplanning/placement 2 | #Advisor: Yao-Wen Chang 3 | #Author: Jer-Ming Hsu 4 | # Hsun-Cheng Lee 5 | #Sponsors: NSC, Taiwan; Arcadia, Inc; UMC Corp. 6 | #Version: 1.0 7 | #Date: 7/19/2000 8 | 9 | .SUFFIXES: .cc .o 10 | SHELL=/bin/sh 11 | CXX=g++ 12 | DEBUG= -g 13 | OPT= -O2 -DNDEBUG 14 | CXXFLAGS= -c $(DEBUG) $(OPT) 15 | LDFLAGS= 16 | 17 | ########################################################################### 18 | 19 | LIBS = -lstdc++ 20 | OBJS = fplan.o sa.o 21 | B_OBJS = btree.o btree_main.o $(OBJS) 22 | SRCS = ${OBJS:%.o=%.cc} 23 | 24 | all: btree 25 | 26 | btree: $(B_OBJS) 27 | $(CXX) -o btree $(B_OBJS) $(LIBS) $(LDFLAGS) 28 | 29 | %.o : %.cc %.h fplan.h btree.h 30 | $(CXX) $*.cc $(CXXFLAGS) 31 | 32 | %.o : %.cc fplan.h btree.h 33 | $(CXX) $*.cc $(CXXFLAGS) 34 | 35 | clean: 36 | rm -f *.o btree *~ 37 | 38 | compact : btree 39 | strip $? 40 | 41 | -------------------------------------------------------------------------------- /B*树算法/sa.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | #ifndef sa_btreeH 3 | #define sa_btreeH 4 | //--------------------------------------------------------------------------- 5 | #include "fplan.h" 6 | //--------------------------------------------------------------------------- 7 | extern float init_avg; 8 | extern float avg_ratio; 9 | extern float lamda; 10 | 11 | double SA_Floorplan(FPlan &fp, int k, int local=0, float term_T=0.1); 12 | double Random_Floorplan(FPlan &fp,int times); 13 | //--------------------------------------------------------------------------- 14 | #endif 15 | -------------------------------------------------------------------------------- /LSM树算法/LSM.c: -------------------------------------------------------------------------------- 1 | 正在抓紧更新中... 2 | -------------------------------------------------------------------------------- /RSA加密算法/rsa.c: -------------------------------------------------------------------------------- 1 | /* 2 | *RSA加解密算法 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | 9 | #define P 5 10 | #define Q 7 11 | 12 | #define N (P*Q) 13 | #define Z ((P - 1)*(Q - 1)) 14 | 15 | #define E 5 16 | #define D 5 17 | 18 | 19 | 20 | int main(void) 21 | { 22 | int i; 23 | int TrsMsg[4] = {12, 15, 22, 5}; 24 | long en[4], de[4]; 25 | int SecCode[4], DeMsg[4]; 26 | 27 | printf("下面是一个RSA加解密算法的简单演示:\n"); 28 | printf("\t Copyright(C) Long.Luo.\n\n"); 29 | printf("报文\t加密\t 加密后密文\n"); 30 | 31 | for (i=0; i<4; i++) 32 | { 33 | en[i] = (int)pow(TrsMsg[i], E); 34 | SecCode[i] = en[i] % N; 35 | 36 | printf("%d\t%d\t\t%d\n", TrsMsg[i], en[i], SecCode[i]); 37 | } 38 | 39 | printf("\n原始报文\t密文\t加密\t\t解密报文\n"); 40 | for (i=0; i<4; i++) 41 | { 42 | de[i] = pow(SecCode[i], D); 43 | DeMsg[i] = de[i] % N; 44 | 45 | printf("%d\t\t%d\t%d\t\t%d\n", TrsMsg[i], SecCode[i], de[i], DeMsg[i]); 46 | } 47 | 48 | getchar(); 49 | 50 | return 0; 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /三色棋/hree-Color_Flag.c: -------------------------------------------------------------------------------- 1 | /* 2 | 三色棋 3 | */ 4 | #include 5 | #include 6 | #include 7 | #define BLUE 'b' 8 | #define WHITE 'w' 9 | #define RED 'r' 10 | #define SWAP(x, y) { char temp; \ 11 | temp = color[x]; \ 12 | color[x] = color[y]; \ 13 | color[y] = temp; } 14 | int main() { 15 | char color[] = {'r', 'w', 'b', 'w', 'w', 16 | 'b', 'r', 'b', 'w', 'r', '\0'}; 17 | int wFlag = 0; 18 | int bFlag = 0; 19 | int rFlag = strlen(color) - 1; 20 | int i; 21 | for(i = 0; i < strlen(color); i++) 22 | printf("%c ", color[i]); 23 | printf("\n"); 24 | while(wFlag <= rFlag) { 25 | if(color[wFlag] == WHITE) 26 | wFlag++; 27 | else if(color[wFlag] == BLUE) { 28 | SWAP(bFlag, wFlag); 29 | bFlag++; wFlag++; 30 | } 31 | else { 32 | while(wFlag < rFlag && color[rFlag] == RED) 33 | rFlag--; 34 | SWAP(rFlag, wFlag); 35 | rFlag--; 36 | } 37 | } 38 | for(i = 0; i < strlen(color); i++) 39 | printf("%c ", color[i]); 40 | printf("\n"); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /三角矩阵/三角矩阵.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() 5 | { 6 | double l[100][100],a[100][100]; 7 | double sum1,sum2; 8 | int n; 9 | int k,j,m; 10 | scanf("%d",&n); 11 | for(k=0;kj)printf(" "); 50 | else printf("%-10lf" ,l[k][j]); 51 | if(j==n-1)printf("\n"); //按照格式输出矩阵 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /乱数排列/乱数排列.c: -------------------------------------------------------------------------------- 1 | /* 2 | 洗扑克牌(乱数排列) 3 | 说明 4 | 洗扑克牌的原理其实与乱数排列是相同的,都是将一组数字(例如1~N)打乱重新排列,只 5 | 不过洗扑克牌多了一个花色判断的动作而已。 6 | 解法 7 | 初学者通常会直接想到,随机产生1~N的乱数并将之存入阵列中,后来产生的乱数存入阵列 8 | 前必须先检查阵列中是否已有重复的数字,如果有这个数就不存入,再重新产生下一个数,运 9 | 气不好的话,重复的次数就会很多,程式的执行速度就很慢了,这不是一个好方法。 10 | 以1~52的乱数排列为例好了,可以将阵列先依序由1到52填入,然后使用一个回圈走访阵列, 11 | 并随机产生1~52的乱数,将产生的乱数当作索引取出阵列值,并与目前阵列走访到的值相交换, 12 | 如此就不用担心乱数重复的问题了,阵列走访完毕后,所有的数字也就重新排列了。 13 | 至于如何判断花色?这只是除法的问题而已,取商数判断花色,取余数判断数字,您可以直接 14 | 看程式比较清楚。 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #define N 52 21 | int main(void) { 22 | int poker[N + 1]; 23 | int i, j, tmp, remain; 24 | // 初始化阵列 25 | for(i = 1; i <= N; i++) 26 | poker[i] = i; 27 | srand(time(0)); 28 | // 洗牌 29 | for(i = 1; i <= N; i++) { 30 | j = rand() % 52 + 1; 31 | tmp = poker[i]; 32 | poker[i] = poker[j]; 33 | poker[j] = tmp; 34 | } 35 | for(i = 1; i <= N; i++) { 36 | // 判断花色 37 | switch((poker[i]-1) / 13) { 38 | case 0: 39 | printf("桃"); break; 40 | case 1: 41 | printf("心"); break; 42 | case 2: 43 | printf("砖"); break; 44 | case 3: 45 | printf("梅"); break; 46 | } 47 | // 扑克牌数字 48 | remain = poker[i] % 13; 49 | switch(remain) { 50 | case 0: 51 | printf("K "); break; 52 | case 12: 53 | printf("Q "); break; 54 | case 11: 55 | printf("J "); break; 56 | default: 57 | printf("%d ", remain); break; 58 | } 59 | if(i % 13 == 0) 60 | printf("\n"); 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /二分查找算法/BinarySearch.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 实现二分查找 4 | #include 5 | #include 6 | 7 | void BinarySearch(int *arr, int start, int end, int num); 8 | 9 | int main(int argc, const char * argv[]) 10 | { 11 | int array[] = {4,5,6,7,8,9}; 12 | 13 | BinarySearch(array, 0, 5, 99); 14 | 15 | return 0; 16 | } 17 | 18 | void BinarySearch(int *arr, int start, int end, int num) 19 | { 20 | int mid = (start + end) / 2; 21 | if (arr[mid] == num) 22 | { 23 | printf("%d ",mid); 24 | return ; 25 | } 26 | 27 | if (start == end) 28 | { 29 | printf("没有找到"); 30 | return ; 31 | } 32 | 33 | if (num < arr[mid]) 34 | { 35 | BinarySearch(arr, start, mid, num); 36 | } 37 | 38 | if (num > arr[mid]) 39 | { 40 | BinarySearch(arr, mid + 1, end, num); 41 | } 42 | 43 | return ; 44 | } -------------------------------------------------------------------------------- /二叉堆/binheap.h: -------------------------------------------------------------------------------- 1 | typedef int ElementType; 2 | 3 | /* START: fig6_4.txt */ 4 | #ifndef _BinHeap_H 5 | #define _BinHeap_H 6 | 7 | struct HeapStruct; 8 | typedef struct HeapStruct *PriorityQueue; 9 | 10 | PriorityQueue Initialize( int MaxElements ); 11 | void Destroy( PriorityQueue H ); 12 | void MakeEmpty( PriorityQueue H ); 13 | void Insert( ElementType X, PriorityQueue H ); 14 | ElementType DeleteMin( PriorityQueue H ); 15 | ElementType FindMin( PriorityQueue H ); 16 | int IsEmpty( PriorityQueue H ); 17 | int IsFull( PriorityQueue H ); 18 | 19 | #endif 20 | 21 | /* END */ 22 | -------------------------------------------------------------------------------- /二叉堆/fatal.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define Error( Str ) FatalError( Str ) 5 | #define FatalError( Str ) fprintf( stderr, "%s\n", Str ), exit( 1 ) 6 | -------------------------------------------------------------------------------- /二叉堆/main.c: -------------------------------------------------------------------------------- 1 | #include "binheap.h" 2 | #include 3 | 4 | #define MaxSize (1000) 5 | 6 | int main() 7 | { 8 | PriorityQueue H; 9 | int i, j; 10 | 11 | H = Initialize(MaxSize); 12 | 13 | // 循环插入 MaxSize 个数字 14 | for (i = 0, j = MaxSize / 2; i < MaxSize; i++, j = (j + 71) % MaxSize) 15 | Insert(j, H); 16 | 17 | j = 0; 18 | 19 | #if 0 20 | while (!IsEmpty(H)) 21 | { 22 | int ele = DeleteMin(H); 23 | printf("%d ", ele); 24 | } 25 | printf("\n"); 26 | #endif 27 | 28 | 29 | while (!IsEmpty(H)) 30 | if (DeleteMin(H) != j++) 31 | printf("Error in DeleteMin, %d\n", j); 32 | 33 | printf("Done...\n"); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /二叉树排序/binary_tree_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef struct node{ 5 | int value; 6 | struct node *l; 7 | struct node *r; 8 | }NODE; 9 | /*插入*/ 10 | NODE *sort(NODE *head, int d); 11 | /*输出*/ 12 | void output(NODE *head); 13 | /*初始化*/ 14 | NODE *createnode(int value); 15 | void main() 16 | { 17 | NODE *head = NULL; 18 | int d; 19 | /*0 作为输入的结束*/ 20 | while(1) 21 | { 22 | scanf("%d", &d); 23 | if (!d) 24 | break; 25 | else 26 | { 27 | if ( head == NULL){ 28 | head = createnode(d); 29 | continue; 30 | } 31 | else 32 | sort(head, d); 33 | } 34 | } 35 | 36 | output(head); 37 | } 38 | NODE *sort(NODE *head, int d) 39 | { 40 | NODE *p; 41 | p = head; 42 | 43 | if ((p->value > d) && (p->l == NULL)){ 44 | p->l = createnode(d); 45 | return p; 46 | } 47 | if((p->value < d) && (p->r == NULL)){ 48 | p->r = createnode(d); 49 | return p; 50 | } 51 | if (p->value == d) 52 | return p; 53 | if(p->value > d) 54 | p = sort(p->l, d); 55 | else 56 | p = sort(p->r, d); 57 | 58 | } 59 | NODE *createnode(int d) 60 | { 61 | NODE *p; 62 | p = (NODE*)malloc(sizeof(NODE)); 63 | p->value = d; 64 | p->l = NULL; 65 | p->r = NULL; 66 | return p; 67 | } 68 | /*中顺输出*/ 69 | void output(NODE *head) 70 | { 71 | NODE *p; 72 | p = head; 73 | if (head == NULL ) 74 | return; 75 | output(p->l); 76 | printf("%-5d", p->value); 77 | output(p->r); 78 | } 79 | -------------------------------------------------------------------------------- /二叉树算法/BinaryTree.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/二叉树算法/BinaryTree.c -------------------------------------------------------------------------------- /二叉树算法/README.md: -------------------------------------------------------------------------------- 1 | ## 二叉树的遍历算法 2 | 3 | 二叉树的遍历主要分为三种:先序遍历,中序遍历和后序遍历。还有一种就是按照层次遍历。 4 | 按照惯例,左孩子优先于右孩子,那么: 5 | 6 | * 先序遍历指的就是先访问本节点,再访问该节点的左孩子和右孩子; 7 | * 中序遍历指的就是:先访问左孩子,再访问本节点,最后访问右孩子; 8 | * 后序遍历指的就是:先访问左右孩子,最后访问本节点。 9 | * 层次遍历:按照树的每一层(高度)进行遍历。 10 | 11 | 树的节点的数据结构常声明为: 12 | ```C++ 13 | struct TreeNode { 14 | int val; 15 | TreeNode *left; //左孩子节点 16 | TreeNode *right; //右孩子节点 17 | TreeNode(int x) : val(x), left(NULL), right(NULL) {} 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /二项堆/binomial_heap.h: -------------------------------------------------------------------------------- 1 | #ifndef _BINOMIAL_HEAP_H_ 2 | #define _BINOMIAL_HEAP_H_ 3 | 4 | typedef int Type; 5 | 6 | typedef struct _BinomialNode{ 7 | Type key; // 关键字(键值) 8 | int degree; // 度数 9 | struct _BinomialNode *child; // 左孩子 10 | struct _BinomialNode *parent; // 父节点 11 | struct _BinomialNode *next; // 兄弟 12 | }BinomialNode, *BinomialHeap; 13 | 14 | // 新建key对应的节点,并将其插入到二项堆中。 15 | BinomialNode* binomial_insert(BinomialHeap heap, Type key); 16 | // 删除节点:删除键值为key的节点,并返回删除节点后的二项树 17 | BinomialNode* binomial_delete(BinomialHeap heap, Type key); 18 | // 将二项堆heap的键值oldkey更新为newkey 19 | void binomial_update(BinomialHeap heap, Type oldkey, Type newkey); 20 | 21 | // 合并二项堆:将h1, h2合并成一个堆,并返回合并后的堆 22 | BinomialNode* binomial_union(BinomialHeap h1, BinomialHeap h2) ; 23 | 24 | // 查找:在二项堆中查找键值为key的节点 25 | BinomialNode* binomial_search(BinomialHeap heap, Type key); 26 | // 获取二项堆中的最小节点 27 | BinomialNode* binomial_minimum(BinomialHeap heap) ; 28 | // 移除最小节点,并返回移除节点后的二项堆 29 | BinomialNode* binomial_extract_minimum(BinomialHeap heap); 30 | 31 | // 打印"二项堆" 32 | void binomial_print(BinomialHeap heap); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /伸展树算法/README.md: -------------------------------------------------------------------------------- 1 | ## 伸展树 2 | 3 | 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性。即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x, 4 | 而其右子树中的每一个元素都大于 x。与普通二叉查找树不同的是,伸展树可以自我调整,这就要依靠伸展操作 Splay(x,S)。 5 | 6 | ## 伸展树的基本操作 7 | 8 | 利用 Splay 操作,我们可以在伸展树 S 上进行如下运算: 9 | 1. Find(x,S):判断元素 x 是否在伸展树 S 表示的有序集中。 10 | 首先,与在二叉查找树中的查找操作一样,在伸展树中查找元素 x。如果 x 11 | 在树中,则再执行 Splay(x,S)调整伸展树。 12 | 2. Insert(x,S):将元素 x 插入伸展树 S 表示的有序集中。 13 | 首先,也与处理普通的二叉查找树一样,将 x 插入到伸展树 S 中的相应位置 14 | 上,再执行 Splay(x,S)。 15 | 3. Delete(x,S):将元素 x 从伸展树 S 所表示的有序集中删除。 16 | 首先,用在二叉查找树中查找元素的方法找到 x 的位置。如果 x 没有孩子或 17 | 只有一个孩子,那么直接将 x 删去,并通过 Splay 操作,将 x 节点的父节点调整 18 | 到伸展树的根节点处。否则,则向下查找 x 的后继 y,用 y 替代 x 的位置,最后 19 | 执行 Splay(y,S),将 y 调整为伸展树的根。 20 | 4. Join(S1,S2):将两个伸展树 S1 与 S2 合并成为一个伸展树。其中 S1 的所 21 | 有元素都小于 S2 的所有元素。 22 | 首先,我们找到伸展树 S1 中最大的一个元素 x,再通过 Splay(x,S1)将 x 调 23 | 整到伸展树 S1 的根。然后再将 S2 作为 x 节点的右子树。这样,就得到了新的 24 | 伸展树 S。如图所示 25 | ![image](https://user-images.githubusercontent.com/87458342/129528167-0a915927-9529-4208-ae59-08ed3a7f8f6b.png) 26 | 5. Split(x,S):以 x 为界,将伸展树 S 分离为两棵伸展树 S1 和 S2,其中 S1 27 | 中所有元素都小于 x,S2 中的所有元素都大于 x。 28 |   首先执行 Find(x,S),将元素 x 调整为伸展树的根节点,则 x 的左子树就是 29 | S1,而右子树为 S2。如图所示 30 | ![image](https://user-images.githubusercontent.com/87458342/129528124-fb320e31-427e-4a94-ac4f-41b44f65795d.png) 31 | 32 | -------------------------------------------------------------------------------- /伸展树算法/splay_tree.h: -------------------------------------------------------------------------------- 1 | #ifndef _SPLAY_TREE_H 2 | #define _SPLAY_TREE_H 3 | 4 | struct Node; 5 | typedef int ElementType; 6 | typedef struct Node *PtrToNode; 7 | typedef PtrToNode SplayTree; 8 | typedef PtrToNode Position; 9 | 10 | SplayTree MakeEmpty(SplayTree T); 11 | Position Find(ElementType X,SplayTree T); 12 | Position FindMax(SplayTree T); 13 | Position FindMin(SplayTree T); 14 | SplayTree Insert(ElementType X,SplayTree T); 15 | SplayTree Delete(ElementType X,SplayTree T); 16 | 17 | #endif 18 | 19 | struct Node 20 | { 21 | ElementType element; 22 | PtrToNode Left; 23 | PtrToNode Right; 24 | PtrToNode Parent; 25 | }; 26 | -------------------------------------------------------------------------------- /八枚银币/八枚银币.c: -------------------------------------------------------------------------------- 1 | /* 2 | 八枚银币 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | void compare(int[], int, int, int); 9 | void eightcoins(int[]); 10 | int main(void) { 11 | int coins[8] = {0}; 12 | int i; 13 | srand(time(NULL)); 14 | for(i = 0; i < 8; i++) 15 | coins[i] = 10; 16 | printf("\n输入假币重量(比10大或小):"); 17 | scanf("%d", &i); 18 | coins[rand() % 8] = i; 19 | eightcoins(coins); 20 | printf("\n\n列出所有钱币重量:"); 21 | for(i = 0; i < 8; i++) 22 | printf("%d ", coins[i]); 23 | printf("\n"); 24 | return 0; 25 | } 26 | void compare(int coins[], int i, int j, int k) { 27 | if(coins[i] > coins[k]) 28 | printf("\n假币%d 较重", i+1); 29 | else 30 | printf("\n假币%d 较轻", j+1); 31 | } 32 | void eightcoins(int coins[]) { 33 | if(coins[0]+coins[1]+coins[2] == 34 | coins[3]+coins[4]+coins[5]) { 35 | if(coins[6] > coins[7]) 36 | compare(coins, 6, 7, 0); 37 | else 38 | compare(coins, 7, 6, 0); 39 | } 40 | else if(coins[0]+coins[1]+coins[2] > 41 | coins[3]+coins[4]+coins[5]) { 42 | if(coins[0]+coins[3] == coins[1]+coins[4]) 43 | compare(coins, 2, 5, 0); 44 | else if(coins[0]+coins[3] > coins[1]+coins[4]) 45 | compare(coins, 0, 4, 1); 46 | if(coins[0]+coins[3] < coins[1]+coins[4]) 47 | compare(coins, 1, 3, 0); 48 | } 49 | else if(coins[0]+coins[1]+coins[2] < 50 | coins[3]+coins[4]+coins[5]) { 51 | if(coins[0]+coins[3] == coins[1]+coins[4]) 52 | compare(coins, 5, 2, 0); 53 | else if(coins[0]+coins[3] > coins[1]+coins[4]) 54 | compare(coins, 3, 1, 0); 55 | if(coins[0]+coins[3] < coins[1]+coins[4]) 56 | compare(coins, 4, 0, 1); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /八皇后/八皇后.c: -------------------------------------------------------------------------------- 1 | /* 2 | 八皇后 3 | */ 4 | #include 5 | #include 6 | #define N 8 7 | int column[N+1]; // 同栏是否有皇后,1表示有 8 | int rup[2*N+1]; // 右上至左下是否有皇后 9 | int lup[2*N+1]; // 左上至右下是否有皇后 10 | int queen[N+1] = {0}; 11 | int num; // 解答编号 12 | void backtrack(int); // 递回求解 13 | int main(void) { 14 | int i; 15 | num = 0; 16 | for(i = 1; i <= N; i++) 17 | column[i] = 1; 18 | for(i = 1; i <= 2*N; i++) 19 | rup[i] = lup[i] = 1; 20 | backtrack(1); 21 | return 0; 22 | } 23 | void showAnswer() { 24 | int x, y; 25 | printf("\n解答%d\n", ++num); 26 | for(y = 1; y <= N; y++) { 27 | for(x = 1; x <= N; x++) { 28 | if(queen[y] == x) { 29 | printf(" Q"); 30 | } 31 | else { 32 | printf(" ."); 33 | } 34 | } 35 | printf("\n"); 36 | } 37 | } 38 | void backtrack(int i) { 39 | int j; 40 | if(i > N) { 41 | showAnswer(); 42 | } 43 | else { 44 | for(j = 1; j <= N; j++) { 45 | if(column[j] == 1 && 46 | rup[i+j] == 1 && lup[i-j+N] == 1) { 47 | queen[i] = j; 48 | column[j] = rup[i+j] = lup[i-j+N] = 0; 49 | backtrack(i+1); 50 | column[j] = rup[i+j] = lup[i-j+N] = 1; 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /冒泡排序算法/BubbleSortMain.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/冒泡排序算法/BubbleSortMain.c -------------------------------------------------------------------------------- /冒泡排序算法/README.md: -------------------------------------------------------------------------------- 1 | # BubbleSort01 2 | 数据结构&算法,排序,冒泡排序算法,BubbleSort 3 | -------------------------------------------------------------------------------- /分块查找/分块查找.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | struct index { //定义块的结构 4 | int key; 5 | int start; 6 | } newIndex[3]; //定义结构体数组 7 | int search(int key, int a[]); 8 | int cmp(const void *a,const void* b){ 9 | return (*(struct index*)a).key>(*(struct index*)b).key?1:-1; 10 | } 11 | int main(){ 12 | int i, j=-1, k, key; 13 | int a[] = {33,42,44,38,24,48, 22,12,13,8,9,20, 60,58,74,49,86,53}; 14 | //确认模块的起始值和最大值 15 | for (i=0; i<3; i++) { 16 | newIndex[i].start = j+1; //确定每个块范围的起始值 17 | j += 6; 18 | for (int k=newIndex[i].start; k<=j; k++) { 19 | if (newIndex[i].key0) { 32 | printf("查找成功!您要找的数在数组中的位置是:%d\n",k+1); 33 | }else{ 34 | printf("查找失败!您要找的数不在数组中。\n"); 35 | } 36 | return 0; 37 | } 38 | int search(int key, int a[]){ 39 | int i, startValue; 40 | i = 0; 41 | while (i<3 && key>newIndex[i].key) { //确定在哪个块中,遍历每个块,确定 key 在哪个块中 42 | i++; 43 | } 44 | if (i>=3) { //大于分得的块数,则返回 0 45 | return -1; 46 | } 47 | startValue = newIndex[i].start; //startValue 等于块范围的起始值 48 | while (startValue <= startValue+5 && a[startValue]!=key) 49 | { 50 | startValue++; 51 | } 52 | if (startValue>startValue+5) { //如果大于块范围的结束值,则说明没有要查找的数 53 | return -1;} 54 | return startValue; 55 | } 56 | //运行结果: 57 | //请输入您想要查找的数: 58 | //22 59 | //查找成功!您要找的数在数组中的位置是:7 60 | -------------------------------------------------------------------------------- /分治算法/分治算法.c: -------------------------------------------------------------------------------- 1 | //分治算法 2 | #include 3 | 4 | int MaxSubSum(int *a, int left, int right); 5 | int MaxSum(int n, int *a); 6 | 7 | int main() 8 | { 9 | int a[] = { -2, 11, -4, 13, -5, -2 }; 10 | for (int i = 0; i<6; i++) 11 | { 12 | printf("%d ", a[i]); 13 | } 14 | printf("\n"); 15 | printf("数组a的最大连续子段和为:%d\n", MaxSum(6, a)); 16 | return 0; 17 | } 18 | 19 | int MaxSubSum(int *a, int left, int right) 20 | { 21 | int sum = 0; 22 | if (left == right) 23 | { 24 | sum = a[left]>0 ? a[left] : 0; 25 | } 26 | else 27 | { 28 | int center = (left + right) / 2; 29 | int leftsum = MaxSubSum(a, left, center); 30 | int rightsum = MaxSubSum(a, center + 1, right); 31 | int s1 = 0; 32 | int lefts = 0; 33 | for (int i = center; i >= left; i--) 34 | { 35 | lefts += a[i]; 36 | if (lefts>s1) 37 | { 38 | s1 = lefts; 39 | } 40 | } 41 | int s2 = 0; 42 | int rights = 0; 43 | for (int i = center + 1; i <= right; i++) 44 | { 45 | rights += a[i]; 46 | if (rights>s2) 47 | { 48 | s2 = rights; 49 | } 50 | } 51 | sum = s1 + s2; 52 | if (sum 3 | 4 | int MaxSum(int n, int *a); 5 | 6 | int main() 7 | { 8 | int a[] = { -2, 11, -4, 13, -5, -2 }; 9 | for (int i = 0; i<6; i++) 10 | { 11 | printf("%d ", a[i]); 12 | } 13 | printf("\n"); 14 | printf("数组a的最大连续子段和为:%d\n", MaxSum(6, a)); 15 | return 0; 16 | } 17 | 18 | int MaxSum(int n, int *a) 19 | { 20 | int sum = 0, b = 0; 21 | for (int i = 1; i <= n; i++) 22 | { 23 | if (b>0) 24 | { 25 | b += a[i]; 26 | } 27 | else 28 | { 29 | b = a[i]; 30 | } 31 | if (b>sum) 32 | { 33 | sum = b; 34 | } 35 | } 36 | return sum; 37 | } -------------------------------------------------------------------------------- /单链表算法/LinkList.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/单链表算法/LinkList.c -------------------------------------------------------------------------------- /单链表算法/README.md: -------------------------------------------------------------------------------- 1 | ### 单向链表概念 2 | 3 | 单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。链表是使用指针进行构造的列表,并且是由一个个结点组装起来的,因此又称为结点列表。其中每个结点都有指针成员变量指向列表中的下一个结点,head指针指向第一个结点称为表头,而终止于最后一个指向nuLL的指针。 4 | 5 | ![image](https://user-images.githubusercontent.com/87458342/129359359-5020813d-8315-4715-830b-efac1e857472.png) 6 | 7 | 8 | ### 单向链表结构特征: 9 | 1. 单向:只有前到后的方向 10 | 2. 节点=数据域+引用域 11 | 3. self.__head引用第一个有效节点,如果链表为空则引用空 12 | 4. 第一个节点称之为头节点,最后一个节点称之为尾节点 13 | 5. 尾节点的引用与指空 14 | -------------------------------------------------------------------------------- /双向链表算法/DoubleList.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/双向链表算法/DoubleList.c -------------------------------------------------------------------------------- /双向链表算法/README.md: -------------------------------------------------------------------------------- 1 | ## 双向链表 2 | 3 | 双链表是链表的一种,由节点组成,每个数据结点中都有两个指针,分别指向直接后继和直接前驱。 4 | 5 | ![image](https://user-images.githubusercontent.com/87458342/129358264-8c0ac9a9-6b01-4759-aad0-31f09d17c5bc.png) 6 | 7 | ## 双向链表类的基本结构 8 | 9 | ```C++ 10 | template 11 | class DualLinkedList:public List 12 | { 13 | protected: 14 | struct Node:public Object 15 | { 16 | T value;//数据域 17 | Node* next;//后继指针域 18 | Node* pre;//前驱 19 | }; 20 | mutable struct:public Object 21 | { 22 | char reserved[sizeof(T)];//占位空间 23 | Node* next; 24 | Node* pre; 25 | }m_header; 26 | int m_length; 27 | int m_step; 28 | Node* m_current; 29 | } 30 | ``` 31 | 32 | ## 双向链表的操作 33 | ![image](https://user-images.githubusercontent.com/87458342/129358571-c3c9eef1-bded-4b4e-b47f-9c9e2c7b1b25.png) 34 | 35 | ![image](https://user-images.githubusercontent.com/87458342/129358650-a9adde6b-ee7e-42c7-955b-e1cd21b1a8ee.png) 36 | 37 | -------------------------------------------------------------------------------- /后序式/后序式.c: -------------------------------------------------------------------------------- 1 | /* 2 | 后序式的运算 3 | 说明将中序式转换为后序式的好处是,不用处理运算子先后顺序问题,只要依序由运算式由 4 | 前往后读取即可。 5 | */ 6 | 7 | #include 8 | #include 9 | void evalPf(char*); 10 | double cal(double, char, double); 11 | int main(void) { 12 | char input[80]; 13 | printf("输入后序式:"); 14 | scanf("%s", input); 15 | evalPf(input); 16 | return 0; 17 | } 18 | void evalPf(char* postfix) { 19 | double stack[80] = {0.0}; 20 | char temp[2]; 21 | char token; 22 | int top = 0, i = 0; 23 | temp[1] = '\0'; 24 | while(1) { 25 | token = postfix[i]; 26 | switch(token) { 27 | case '\0': 28 | printf("ans = %f\n", stack[top]); 29 | return; 30 | case '+': case '-': case '*': case '/': 31 | stack[top-1] = 32 | cal(stack[top], token, stack[top-1]); 33 | top--; 34 | break; 35 | default: 36 | if(top < sizeof(stack) / sizeof(float)) { 37 | temp[0] = postfix[i]; 38 | top++; 39 | stack[top] = atof(temp); 40 | } 41 | break; 42 | } 43 | i++; 44 | } 45 | } 46 | double cal(double p1, char op, double p2) { 47 | switch(op) { 48 | case '+': 49 | return p1 + p2; 50 | case '-': 51 | return p1 - p2; 52 | case '*': 53 | return p1 * p2; 54 | case '/': 55 | return p1 / p2; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /回溯算法/回溯算法.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int cs,n,m; 6 | int a[100]; 7 | void f(int t) 8 | { 9 | int i,j; 10 | if(cs==m) 11 | { 12 | for(i=1;i<=m;i++) 13 | { 14 | cout<cs) 29 | { 30 | cs++; 31 | a[cs]=i; 32 | f(i); 33 | } 34 | } 35 | cs--; 36 | } 37 | } 38 | 39 | int main() 40 | { 41 | cout<<"Please enter the number of 'n' :"; 42 | cin>>n; 43 | cout<<"Enter the number of elements to take out the arrangement 'm' :"; 44 | cin>>m; 45 | cs=0; 46 | f(0); 47 | return 0; 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /图/完全图/完全图.c: -------------------------------------------------------------------------------- 1 | 正在更新中... 2 | -------------------------------------------------------------------------------- /图/无向图/无向图.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | #define MAX 10000 //MAX表示最大节点数 7 | #define INF 10000 //设定两个节点之间不可达的情况下权重为INF 8 | 9 | struct edge { 10 | int to,cost; //每条边都有一个目的节点和权重 11 | }; 12 | 13 | 14 | vector es[MAX]; //边的数组元素是以edge为元素的队列 15 | 16 | int d[MAX]; //节点i到所有节点的距离 17 | int v,e; //节点个数和边的个数 18 | 19 | //构造图 20 | void build() 21 | { 22 | printf("please input the number of vertex and edge\n"); 23 | scanf("%d %d",&v,&e); 24 | printf("please input from,to,and cost of all edges\n"); 25 | for(int i=0;i 6 | #include 7 | int main(void) { 8 | int arr1[3][4] = {{1, 2, 3, 4}, 9 | {5, 6, 7, 8}, 10 | {9, 10, 11, 12}}; 11 | int arr2[12] = {0}; 12 | int row, column, i; 13 | printf("原二维资料:\n"); 14 | for(row = 0; row < 3; row++) { 15 | for(column = 0; column < 4; column++) { 16 | printf("%4d", arr1[row][column]); 17 | } 18 | printf("\n"); 19 | } 20 | printf("\n以列为主:"); 21 | for(row = 0; row < 3; row++) { 22 | for(column = 0; column < 4; column++) { 23 | i = column + row * 4; 24 | arr2[i] = arr1[row][column]; 25 | } 26 | } 27 | for(i = 0; i < 12; i++) 28 | printf("%d ", arr2[i]); 29 | printf("\n以行为主:"); 30 | for(row = 0; row < 3; row++) { 31 | for(column = 0; column < 4; column++) { 32 | i = row + column * 3; 33 | arr2[i] = arr1[row][column]; 34 | } 35 | } 36 | for(i = 0; i < 12; i++) 37 | printf("%d ", arr2[i]); 38 | printf("\n"); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /大数运算/大数运算.c: -------------------------------------------------------------------------------- 1 | /* 2 | 超长整数运算(大数运算) 3 | 说明基于记忆体的有效运用,程式语言中规定了各种不同的资料型态,也因此变数所可以表 4 | 达的最大整数受到限制,例如123456789123456789这样的整数就不可能储存在long变数中(例 5 | 如C/C++等),我们称这为long数,这边翻为超长整数(避免与资料型态的长整数翻译混淆),或 6 | 俗称大数运算。 7 | 解法一个变数无法表示超长整数,则就使用多个变数,当然这使用阵列最为方便,假设程式 8 | 语言的最大资料型态可以储存至65535的数好了,为了计算方便及符合使用十进位制的习惯,让 9 | 每一个阵列元素可以储存四个位数,也就是0到9999的数,例如: 10 | 很多人问到如何计算像50!这样的问题,解法就是使用程式中的乘法函式,至于要算到多大,就 11 | 看需求了。 12 | 由于使用阵列来储存数值,关于数值在运算时的加减乘除等各种运算、位数的进位或借位就必 13 | 须自行定义,加、减、乘都是由低位数开始运算,而除法则是由高位数开始运算,这边直接提 14 | 供加减乘除运算的函式供作参考,以下的N为阵列长度。 15 | */ 16 | 17 | void add(int *a, int *b, int *c) { 18 | int i, carry = 0; 19 | for(i = N - 1; i >= 0; i--) { 20 | c[i] = a[i] + b[i] + carry; 21 | if(c[i] < 10000) 22 | carry = 0; 23 | else { // 进位 24 | c[i] = c[i] - 10000; 25 | carry = 1; 26 | } 27 | } 28 | } 29 | void sub(int *a, int *b, int *c) { 30 | int i, borrow = 0; 31 | for(i = N - 1; i >= 0; i--) { 32 | c[i] = a[i] - b[i] - borrow; 33 | if(c[i] >= 0) 34 | borrow = 0; 35 | else { // 借位 36 | c[i] = c[i] + 10000; 37 | borrow = 1; 38 | } 39 | } 40 | } 41 | void mul(int *a, int b, int *c) { // b 为乘数 42 | int i, tmp, carry = 0; 43 | for(i = N - 1; i >=0; i--) { 44 | tmp = a[i] * b + carry; 45 | c[i] = tmp % 10000; 46 | carry = tmp / 10000; 47 | } 48 | } 49 | void div(int *a, int b, int *c) { // b 为除数 50 | int i, tmp, remain = 0; 51 | for(i = 0; i < N; i++) { 52 | tmp = a[i] + remain; 53 | c[i] = tmp / b; 54 | remain = (tmp % b) * 10000; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /完美数/完美数.c: -------------------------------------------------------------------------------- 1 | /* 2 | 完美数 3 | 4 | */ 5 | 6 | #include 7 | #include 8 | #define N 1000 9 | #define P 10000 10 | int prime(int*); 11 | int factor(int*, int, int*); 12 | int fsum(int*, int); 13 | int main(void) { 14 | int ptable[N+1] = {0}; 15 | int fact[N+1] = {0}; 16 | int count1, count2, i; 17 | count1 = prime(ptable); 18 | for(i = 0; i <= P; i++) { 19 | count2 = factor(ptable, i, fact); 20 | if(i == fsum(fact, count2)) 21 | printf("Perfect Number: %d\n", i); 22 | } 23 | printf("\n"); 24 | return 0; 25 | } 26 | int prime(int* pNum) { 27 | int i, j; 28 | int prime[N+1]; 29 | for(i = 2; i <= N; i++) 30 | prime[i] = 1; 31 | for(i = 2; i*i <= N; i++) { 32 | if(prime[i] == 1) { 33 | for(j = 2*i; j <= N; j++) { 34 | if(j % i == 0) 35 | prime[j] = 0; 36 | } 37 | } 38 | } 39 | for(i = 2, j = 0; i < N; i++) { 40 | if(prime[i] == 1) 41 | pNum[j++] = i; 42 | } 43 | return j; 44 | } 45 | int factor(int* table, int num, int* frecord) { 46 | int i, k; 47 | for(i = 0, k = 0; table[i] * table[i] <= num;) { 48 | if(num % table[i] == 0) { 49 | frecord[k] = table[i]; 50 | k++; 51 | num /= table[i]; 52 | } 53 | else 54 | i++; 55 | } 56 | frecord[k] = num; 57 | return k+1; 58 | } 59 | int fsum(int* farr, int c) { 60 | int i, r, s, q; 61 | i = 0; 62 | r = 1; 63 | s = 1; 64 | q = 1; 65 | while(i < c) { 66 | do { 67 | r *= farr[i]; 68 | q += r; 69 | i++; 70 | } while(i < c-1 && farr[i-1] == farr[i]); 71 | s *= q; 72 | r = 1; 73 | q = 1; 74 | } 75 | return s / 2; 76 | } 77 | -------------------------------------------------------------------------------- /宽度优先搜索/宽度优先搜索.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /对称矩阵/对称矩阵.c: -------------------------------------------------------------------------------- 1 | /* 2 | 对称矩阵 3 | */ 4 | 5 | #include 6 | #include 7 | #define N 5 8 | int main(void) { 9 | int arr1[N][N] = { 10 | {1, 2, 3, 4, 5}, 11 | {0, 6, 7, 8, 9}, 12 | {0, 0, 10, 11, 12}, 13 | {0, 0, 0, 13, 14}, 14 | {0, 0, 0, 0, 15}}; 15 | int arr2[N*(1+N)/2] = {0}; 16 | int i, j, loc = 0; 17 | printf("原二维资料:\n"); 18 | for(i = 0; i < N; i++) { 19 | for(j = 0; j < N; j++) { 20 | printf("%4d", arr1[i][j]); 21 | } 22 | printf("\n"); 23 | } 24 | printf("\n以列为主:"); 25 | for(i = 0; i < N; i++) { 26 | for(j = 0; j < N; j++) { 27 | if(arr1[i][j] != 0) 28 | arr2[loc++] = arr1[i][j]; 29 | } 30 | } 31 | for(i = 0; i < N*(1+N)/2; i++) 32 | printf("%d ", arr2[i]); 33 | printf("\n输入索引(i, j):"); 34 | scanf("%d, %d", &i, &j); 35 | loc = N*i - i*(i+1)/2 + j; 36 | printf("(%d, %d) = %d", i, j, arr2[loc]); 37 | printf("\n"); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /对角矩阵/对角矩阵.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /左倾堆/leftist.h: -------------------------------------------------------------------------------- 1 | #ifndef _LEFTIST_TREE_H_ 2 | #define _LEFTIST_TREE_H_ 3 | 4 | typedef int Type; 5 | 6 | typedef struct _LeftistNode{ 7 | Type key; // 关键字(键值) 8 | int npl; // 零路经长度(Null Path Length) 9 | struct _LeftistNode *left; // 左孩子 10 | struct _LeftistNode *right; // 右孩子 11 | }LeftistNode, *LeftistHeap; 12 | 13 | // 前序遍历"左倾堆" 14 | void preorder_leftist(LeftistHeap heap); 15 | // 中序遍历"左倾堆" 16 | void inorder_leftist(LeftistHeap heap); 17 | // 后序遍历"左倾堆" 18 | void postorder_leftist(LeftistHeap heap); 19 | 20 | // 获取最小值(保存到pval中),成功返回0,失败返回-1。 21 | int leftist_minimum(LeftistHeap heap, int *pval); 22 | // 合并"左倾堆x"和"左倾堆y",并返回合并后的新树 23 | LeftistNode* merge_leftist(LeftistHeap x, LeftistHeap y); 24 | // 将结点插入到左倾堆中,并返回根节点 25 | LeftistNode* insert_leftist(LeftistHeap heap, Type key); 26 | // 删除结点(key为节点的值),并返回根节点 27 | LeftistNode* delete_leftist(LeftistHeap heap); 28 | 29 | // 销毁左倾堆 30 | void destroy_leftist(LeftistHeap heap); 31 | 32 | // 打印左倾堆 33 | void print_leftist(LeftistHeap heap); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /左倾堆/leftist_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * C语言实现的左倾堆 3 | * 4 | * @author skywang 5 | * @date 2014/03/31 6 | */ 7 | 8 | #include 9 | #include "leftist.h" 10 | 11 | #define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) ) 12 | 13 | void main() 14 | { 15 | int i; 16 | int a[]= {10,40,24,30,36,20,12,16}; 17 | int b[]= {17,13,11,15,19,21,23}; 18 | int alen=LENGTH(a); 19 | int blen=LENGTH(b); 20 | LeftistHeap ha,hb; 21 | 22 | ha=hb=NULL; 23 | 24 | printf("== 左倾堆(ha)中依次添加: "); 25 | for(i=0; i 2 | #include 3 | 4 | #include "bloom.h" 5 | 6 | #define SETBIT(a,n) (a[n/CHAR_BIT] |= (1<<(n%CHAR_BIT))) 7 | #define GETBIT(a,n) (a[n/CHAR_BIT] & (1<<(n%CHAR_BIT))) 8 | 9 | BLOOM* bloom_create(size_t size,size_t nfuncs,...) 10 | { 11 | BLOOM* bloom; 12 | va_list l; 13 | int n; 14 | 15 | if (!(bloom = malloc(sizeof(BLOOM)))) return NULL; 16 | if (!(bloom->a = calloc((size+CHAR_BIT-1)/CHAR_BIT,sizeof(char)))) 17 | { 18 | free(bloom); 19 | return NULL; 20 | } 21 | 22 | if (!(bloom->funcs = (hashfunc_t*)malloc(nfuncs*sizeof(hashfunc_t)))) 23 | { 24 | free(bloom->a); 25 | free(bloom); 26 | return NULL; 27 | } 28 | 29 | va_start(l,nfuncs); 30 | for (n = 0; n < nfuncs; ++n) 31 | { 32 | bloom->funcs[n] = va_arg(l,hashfunc_t); 33 | } 34 | va_end(l); 35 | 36 | bloom->nfuncs = nfuncs; 37 | bloom->asize = size; 38 | 39 | return bloom; 40 | } 41 | 42 | int bloom_destroy(BLOOM* bloom) 43 | { 44 | free(bloom->a); 45 | free(bloom->funcs); 46 | free(bloom); 47 | 48 | return 0; 49 | } 50 | 51 | int bloom_add(BLOOM* bloom,const char* s) 52 | { 53 | size_t n; 54 | 55 | for (n = 0; n < bloom->nfuncs; ++n) 56 | { 57 | SETBIT(bloom->a,bloom->funcs[n](s)%bloom->asize); 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | int bloom_check(BLOOM* bloom,const char* s) 64 | { 65 | size_t n; 66 | 67 | for (n = 0; n < bloom->nfuncs; ++n) 68 | { 69 | if (!(GETBIT(bloom->a,bloom->funcs[n](s)%bloom->asize))) return 0; 70 | } 71 | 72 | return 1; 73 | } 74 | -------------------------------------------------------------------------------- /希尔排序算法/README.md: -------------------------------------------------------------------------------- 1 | # 希尔排序ShellSort01 2 | 3 | 关键字:数据结构&算法,排序,希尔排序,直接插入算法(不含哨兵) 4 | 5 | 文件名称:希尔排序ShellSort01(不含哨兵变量) 6 | 7 | 时间:2016-3-7 16:18 8 | 9 | 说明: 10 | 11 | 1、希尔排序ShellSort概念:将含有大量待排记录数的序列按增量间隔分成若干子序列,在这些子序列中分别进行直接插入排序;当整个序列都基本有序时,再对全体记录进行一次直接插入排序。 12 | 13 | 2、时间复杂度o(n^1.5). 14 | 15 | 3、希尔排序ShellSort的关键是选取合适的增量间隔分组进行直接插入排序,增量序列的最后一个增量必须等于1才行。 16 | 17 | -------------------------------------------------------------------------------- /希尔排序算法/ShellSort.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/希尔排序算法/ShellSort.c -------------------------------------------------------------------------------- /平衡二叉树算法/README.md: -------------------------------------------------------------------------------- 1 | # AVLTree 2 | 平衡二叉树 3 | -------------------------------------------------------------------------------- /并查集/README.md: -------------------------------------------------------------------------------- 1 | ## 并查集 2 | 并查集是一种树形结构,又叫“不相交集合”,保持了一组不相交的动态集合,每个集合通过一个代表来识别,代表即集合中的某个成员,通常选择根做这个代表。 3 | 4 | ## 并查集作用 5 | * 并查集主要用于解决分组问题,它用来管理一系列不想交的集合,支持如下两种操作: 6 | * 合并:把两个不相交的集合合并为一个集合 7 | * 查询:查询某个元素的根节点,可以判断两个元素的根节点是否相等判断两个元素是否在一个并查集中。 8 | 9 | ## 并查集三种主要操作 10 | * Make_Set(x): 11 | * 建立一个新的集合,其唯一成员就是x,因此这个集合的代表也是x,并查集要求各集合是不相交的,因此要求x没有在其他集合中出现过。 12 | * Find_Set(x): 13 | * 返回能代表x所在集合的节点,通常返回x所在集合的根节点。有递归和非递归两种方法,下面会有讲解。 14 | * Union(x, y): 15 | * 将包含x,y的动态集合合并为一个新的集合。合并两个集合的关键是找到两个集合的根节点,如果两个根节点相同则不用合并;如果不同,则需要合并。 16 | 17 | ![image](https://user-images.githubusercontent.com/87458342/129165679-a5925115-4a77-4b3e-8d34-88a0d3c4daab.png) 18 | 19 | ## 并查集优化 20 | 21 | * Union(x, y)时按秩合并
22 | 合并时,如果两个集合的秩相同,任选一个根做为父节点,并增加其秩。
23 | 秩不同时,让较小秩的集合指向较大秩的集合,这时秩的大小不变。
24 | 秩和集合的数目是不一样的,秩表示节点高度的一个商界;集合的数目表示集合中节点的总数。 25 | 26 | * Find_Set(x)路径压缩
27 | 在Find_Set(x)中,是查找路径上的每个节点都直接指向根节点,这样下次再找根节点的时间复杂度会变成o(1) 28 | -------------------------------------------------------------------------------- /并查集/并查集.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAXN 1005 4 | typedef long long ll; 5 | int fa[MAXN], rank[MAXN]; 6 | ll X[MAXN], Y[MAXN], Z[MAXN]; 7 | inline bool next_to(ll x1, ll y1, ll z1, ll x2, ll y2, ll z2, ll r) 8 | { 9 | return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2) <= 4 * r * r; 10 | //判断两个空洞是否相交或相切 11 | } 12 | inline void init(int n) 13 | { 14 | for (int i = 1; i <= n; ++i) 15 | { 16 | fa[i] = i; 17 | rank[i] = 1; 18 | } 19 | } 20 | int find(int x) 21 | { 22 | return x == fa[x] ? x : (fa[x] = find(fa[x])); 23 | } 24 | inline void merge(int i, int j) 25 | { 26 | int x = find(i), y = find(j); 27 | if (rank[x] <= rank[y]) 28 | fa[x] = y; 29 | else 30 | fa[y] = x; 31 | if (rank[x] == rank[y] && x != y) 32 | rank[y]++; 33 | } 34 | int main() 35 | { 36 | int T, n, h; 37 | ll r; 38 | scanf("%d", &T); 39 | for (int I = 0; I < T; ++I) 40 | { 41 | memset(X, 0, sizeof(X)); 42 | memset(Y, 0, sizeof(Y)); 43 | memset(Z, 0, sizeof(Z)); 44 | scanf("%d%d%lld", &n, &h, &r); 45 | init(n); 46 | fa[1001] = 1001; //用1001代表底部 47 | fa[1002] = 1002; //用1002代表顶部 48 | for (int i = 1; i <= n; ++i) 49 | scanf("%lld%lld%lld", X + i, Y + i, Z + i); 50 | for (int i = 1; i <= n; ++i) 51 | { 52 | if (Z[i] <= r) 53 | merge(i, 1001); //与底部接触的空洞与底部合并 54 | if (Z[i] + r >= h) 55 | merge(i, 1002); //与顶部接触的空洞与顶部合并 56 | } 57 | for (int i = 1; i <= n; ++i) 58 | { 59 | for (int j = i + 1; j <= n; ++j) 60 | { 61 | if (next_to(X[i], Y[i], Z[i], X[j], Y[j], Z[j], r)) 62 | merge(i, j); //遍历所有空洞,合并相交或相切的球 63 | } 64 | } 65 | printf("%s\n", find(1001) == find(1002) ? "Yes" : "No"); 66 | } 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /开源项目/MiGo开源掌机/README.md: -------------------------------------------------------------------------------- 1 | ## MiGo开源掌机 2 | 3 | 这是一个迷你游戏机项目,演示视频(bilibili),其目的是打造钥匙扣大小的功能齐全的掌机,同时也希望能兼顾掌机爱好者在它上面开发自己的应用。类似于 Arduboy 这个项目,它做的真的很好,很多的游戏爱好者在它上面开发了好几百个游戏,这主要归功于其简单的特性以及支持使用Arduino来开发自己的游戏。遗憾的是,Arduboy 局限于有限的机能(主控芯片为Atmega32u4,32kb falsh + 4kb SRAM),无法做出更好玩的功能。MiGO使用ESP32作为主控芯片,这款芯片功能强大但又足够简单上手,网上资源足够多,支持Arduino编程,所以就使用它了。 4 | 5 | ## 主要功能 6 | 7 | MiGO 都有功能都有那些呢?以下是目前正在实现或者已经实现的一些,但实际上可以有更多的: 8 | 9 | * fc 模拟器,对这是最基本的,实测运行帧率达60帧是完全没有问题的(屏幕分辨率240*240的情况下) 10 | * gbc模拟器 目前网上已经有人在ESP32下实现gbc模拟器了,只需拿过来使用即可; 11 | * gba模拟器 好吧,这个可能有些困难,因为性能可能还是不够,不过如果有人能够找出优化方案或许可以呢? 12 | * sfc模拟器 这个模拟器可以做; 13 | * arduboy模拟器 是的,你没有看错,MiGo其实可以运行Arduboy模拟器然后玩Arduboy游戏,真是非常不错 14 | * xxx模拟器 更多模拟器可能会实现 15 | * 音乐播放器,这个功能已经实现了,在使用软件解码mp3格式的情况下,播放48kHZ的音乐还是没有问题的 16 | * 时间显示,这个功能因为加入了32.768kHz的晶振 17 | * 录音功能, 因为 MiGo 主板上安装有一个MEMS传声器,所以可以用来录音并保存到内存卡; 18 | * 网络通话, 得益于ESP32自带的WIFI功能,结合传声器和扬声器可以实现远程的网络语音聊天 19 | * 游戏联机, 使用蓝牙或者wifi可以在nes模拟器上玩双人游戏; 20 | * 网络收音机,通过wifi来连接Web Radio,这个已经实现了,让MiGO可以当不错的老人机; 21 | * 网络音乐,已经有人通过esp32来播放网易云音乐,那么 MiGO 也一定行; 22 | * 播放视频, 或许这个有一些困难,主要在于解码速率如何,不过值得一式; 23 | * 远程投屏,这个还是挺有意思的,在电脑端搭建一个TCP服务器,MiGO通过WIFI接收电脑的屏幕信息,这个可以让MiGO和电脑互动。 24 | * 无线手柄,MiGO可以通过蓝牙或者wifi来连接电脑来控制电脑上的游戏; 25 | * 连接蓝牙耳机,虽然MiGO有一个3.5mm的耳机插孔,但是还可以通过蓝牙连接像airpod这样的蓝牙耳机; 26 | * 网络电子书浏览器,利用LVGL可以实现一个非常精美的小说阅读器 27 | * ftp文件服务器,web服务器 让MiGO连接上网站,并作为一个服务器,利用内网穿透,将你的网站发布的英特网; 28 | * 英语词典,英语学习机,这个还可以用来学习,没想到吧; 29 | * ... 太多, 省略 30 | 31 | ## Example 32 | 下面是MiGO运行fc模拟器的一个示意图: 33 | 34 | ![image](https://user-images.githubusercontent.com/87458342/128992214-d245f9b3-5746-40b6-b6cc-24976eca7534.png) 35 | 36 | 看起来不错,小巧可爱的!但其实可以做的更小,但那就意味这电池容量不能做大太大,游玩时间缩短了。注意按键下面那个孔,它是用来录音的。旁边留有钥匙孔,可以穿钥匙扣。 37 | 38 | Github: [https://github.com/wjdready/migo](https://github.com/wjdready/migo) 39 | -------------------------------------------------------------------------------- /开源项目/README.md: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /开源项目/game-of-life/Makefile: -------------------------------------------------------------------------------- 1 | .POSIX: 2 | CC = cc -std=c99 3 | CFLAGS = -Wall -Wextra -Os -g3 4 | 5 | lifegen: lifegen.c 6 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lifegen.c $(LDLIBS) 7 | 8 | clean: 9 | rm -f lifegen 10 | -------------------------------------------------------------------------------- /开源项目/game-of-life/README.md: -------------------------------------------------------------------------------- 1 | # Game of Life Makefile Generator 2 | 3 | This program generates Makefiles that run the Game of Life using only macro assignments. 4 | 5 | > $ lifegen > life.mak
6 | > $ make -f life.mak 7 | 8 | Run lifegen -h for the option listing. Custom rulesets and graphics can be chosen. 9 | -------------------------------------------------------------------------------- /开源项目/snake_game/main.c: -------------------------------------------------------------------------------- 1 | //#define _CRT_SECURE_NO_WARNINGS 2 | 3 | #include "snake.h" 4 | 5 | int main() { 6 | init(map, snake);//初始化地图 7 | while (1) { 8 | getKey(); 9 | system("cls"); 10 | Sleep(33); 11 | move(snake, direct);//让蛇开始移动 12 | if (!food[0] && !food[1]) {//食物已经被吃掉--重新生成食物 13 | makeFood(food);//生成食物坐标 14 | } 15 | makeMap(map, snake, food); 16 | showView(map); 17 | if (ifBump(head)) { 18 | printf("游戏结束,你的成绩为:%d", head); 19 | break; 20 | } 21 | getKey(); 22 | } 23 | getchar(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /开源项目/snake_game/snake.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /开源项目/snake_game/snake.h: -------------------------------------------------------------------------------- 1 | //#ifndef __SNAKE_H__ 2 | //#define __SNAKE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | extern int W;//地图宽度 11 | extern int H;//地图高度 12 | 13 | extern char map[22][52];//定义地图 14 | extern char key;//用来保存用户操作时输入的键值 15 | 16 | extern int direct;//蛇当前的运动方向 17 | extern int food[2]; 18 | extern int head;//记录长度 19 | 20 | extern int snake[400][3];//蛇的所有坐标点以及蛇 身体(snake[i][0]=0) 和 蛇头(snake[i][0]=1) 从尾部向头部走 21 | 22 | void init(char map[22][52], int snake[400][3]);//游戏开始的时候初始化 23 | void makeMap(char map[22][52], int snake[400][3], int food[]);//根据move后的蛇和生成的food更改map里面的值---制作地图 24 | void move(int snake[400][3], int direct);//让蛇的坐标进行移动 25 | void makeFood(int food[]);//生成随机数制作一个食物坐标 26 | void showView(char map[22][52]); //绘出视图 27 | int ifEat(int head, int food[2]); //判断食物是否被吃掉 28 | int ifReprat(int snake[400][3], int x, int y);//判断生成的食物是否与蛇有重复 29 | int ifBump(int head);//判断是否会相撞(撞自己或撞墙) 30 | void getKey();//读取键值并重新设置运动方向 31 | 32 | //#endif 33 | -------------------------------------------------------------------------------- /开源项目/中国象棋/chess.in: -------------------------------------------------------------------------------- 1 | efgijigfe 2 | aaaaaaaaa 3 | adaaaaada 4 | babababab 5 | aaaaaaaaa 6 | aaaaaaaaa 7 | cacacacac 8 | adaaaaada 9 | aaaaaaaaa 10 | efhikihfe 11 | llmnlopll 12 | // chess.in 的 a~p 分别对应到 load_word.in 的 “-”到“界” 13 | -------------------------------------------------------------------------------- /开源项目/中国象棋/load_word.in: -------------------------------------------------------------------------------- 1 | - 卒 兵 炮 车 马 象 相 士 将 帅 ~ 楚 河 汉 界 平 进 退 九 八 七 六 五 四 三 二 一 2 | // chess.in 的 a~p 分别对应到 load_word.in 的“-”到“界” 3 | -------------------------------------------------------------------------------- /开源项目/弹弹乐/README.md: -------------------------------------------------------------------------------- 1 | # 弹弹乐 2 | 3 | 一款类似打砖块的C语言控制台游戏 4 | 5 | ### 亮点 6 | * 宝石系统 7 | * 紫金 8 | * 冰霜 9 | * 贪婪 10 | * 恶魔 11 | * 风之 12 | * 疯狂 13 | * 砖块等级 14 | * 一级 15 | * 二级 16 | * 三级 17 | * 地图 18 | * 地图编辑器 19 | * 地图保存与加载 20 | 21 | ## 菜单界面 22 | 23 | ![image](https://user-images.githubusercontent.com/87458342/128999413-43189586-b323-4f5e-87de-adb5acb7504e.png) 24 | 25 | ## 游戏界面 26 | 27 | ![image](https://user-images.githubusercontent.com/87458342/128999449-11bbebf2-b03d-4ce8-8da6-efc77005563d.png) 28 | 29 | ## 帮助界面 30 | 31 | ![image](https://user-images.githubusercontent.com/87458342/128999493-5e9a0471-ed63-4bda-928f-b8ed723d8690.png) 32 | 33 | ## 宝石特效界面 34 | 35 | ![image](https://user-images.githubusercontent.com/87458342/128999519-7cb6430c-b211-43c1-b9e3-bc33c983eef3.png) 36 | 37 | ## 制作地图界面 38 | 39 | ![image](https://user-images.githubusercontent.com/87458342/128999553-d94e13cf-ce1d-439b-8d9d-f85cadaedf9d.png) 40 | 41 | Github: [https://github.com/muxiaozi/bounce-ball](https://github.com/muxiaozi/bounce-ball) 42 | -------------------------------------------------------------------------------- /开源项目/弹球游戏/game.c: -------------------------------------------------------------------------------- 1 | #include"game.h" 2 | 3 | int main() { 4 | initscr(); 5 | noecho(); 6 | cbreak(); 7 | keypad(stdscr, TRUE); 8 | initgame(); 9 | 10 | 11 | signal(14, drawgame); 12 | 13 | struct itimerval itimer; 14 | itimer.it_interval.tv_sec = 0; 15 | itimer.it_interval.tv_usec = 100000; 16 | itimer.it_value.tv_sec = 0; 17 | itimer.it_value.tv_usec = 1000; 18 | setitimer(ITIMER_REAL, &itimer, NULL); 19 | 20 | Opoint.x = cx; 21 | Opoint.y = Y - 4; 22 | 23 | attron(COLOR_PAIR(4)); 24 | gotoxy_putc(Opoint.x, Opoint.y, 'o'); 25 | attroff(COLOR_PAIR(4)); 26 | 27 | 28 | refresh(); 29 | 30 | while(1) { 31 | int c = getch(); 32 | switch(c) { 33 | case KEY_LEFT: 34 | Bdir.x -= 2; 35 | break; 36 | case KEY_RIGHT: 37 | Bdir.x += 2; 38 | break; 39 | case KEY_UP: 40 | if (flag) break; 41 | flag = 1; 42 | Odir.x = dir_r[get_random(12)]; 43 | Odir.y = -1; 44 | char blank[] = ""; 45 | gotoxy_puts(3, Y + 4, blank); 46 | gotoxy_puts(3, Y + 5, blank); 47 | break; 48 | default: 49 | break; 50 | } 51 | } 52 | 53 | getch(); 54 | endwin(); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /开源项目/扫雷游戏/main.c: -------------------------------------------------------------------------------- 1 | #include "game.h" 2 | 3 | menu() 4 | { 5 | printf("*******************************\n"); 6 | printf("**** 欢迎来到扫雷游戏! ****\n"); 7 | printf("**** 1.进入游戏 ****\n"); 8 | printf("**** 0.退出游戏 ****\n"); 9 | printf("*******************************\n"); 10 | } 11 | 12 | void game() 13 | { 14 | char mine[ROWS][COLS] = { 0 }; //置放雷的棋盘 15 | char show[ROWS][COLS] = { 0 }; //展示给玩家的棋盘 16 | InitBoard(mine, ROWS, COLS, '0'); 17 | InitBoard(show, ROWS, COLS, '*'); 18 | ScMinc(mine, ROW, COL); //置雷 19 | //DisplayBoard(mine, ROW, COL); 20 | DisplayBoard(show, ROW, COL); 21 | FindMind(mine, show, ROW, COL);//排雷 22 | } 23 | 24 | void test() 25 | { 26 | int input = 0; 27 | srand((unsigned int)time(NULL)); 28 | do 29 | { 30 | menu(); 31 | printf("请选择:>"); 32 | scanf("%d", &input); 33 | switch (input) 34 | { 35 | case 1: 36 | game(); 37 | break; 38 | case 0: 39 | printf("退出游戏\n"); 40 | break; 41 | default: 42 | printf("输入错误\n"); 43 | } 44 | } while (input); 45 | } 46 | 47 | int main() 48 | { 49 | test(); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /开源项目/扫雷游戏/minesweeper.h: -------------------------------------------------------------------------------- 1 | #ifndef __minesweeper_H__ 2 | #define __minesweeper_H__ 3 | 4 | # define _CRT_SECURE_NO_WARNINGS 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define ROW 9 12 | #define COL 9 13 | 14 | #define ROWS ROW+2 15 | #define COLS COL+2 16 | 17 | #define EASY_COUNT 10 18 | 19 | void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); 20 | void DisplayBoard(char board[ROWS][COLS], int row, int col); 21 | void ScMinc(char board[ROWS][COLS], int row, int col); 22 | void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 23 | char FistStep(char mine[ROWS][COLS], int row, int col, int x, int y); 24 | 25 | #endif __minesweeper_H__ 26 | -------------------------------------------------------------------------------- /开源项目/猜数游戏/game.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | main(){ 6 | FILE *fp; 7 | char a; 8 | int k=0,t=0,n,number,answer,maxnumber,mychoose1,mychoose2,standard;/*将当前时间设置成随机函数的种子,所以每次产生的数都不一样*/ 9 | if ((fp=fopen("README2.txt","r+"))==NULL){ 10 | printf("Cannot open file!\n");exit(0);} 11 | while((a=fgetc(fp))!=EOF) 12 | putchar(a); 13 | 14 | aa: printf("\n 菜单 \n1.开始 2.退出 \n"); 15 | scanf("%d",&mychoose1); 16 | switch(mychoose1){ 17 | case 1: printf(" 请选择难易程度\n1.简单 2.普通 3.困难 4.自定义\n"); 18 | scanf("%d",&standard); 19 | switch(standard){ 20 | case 1:n=pow(10,2);break; 21 | case 2:n=pow(10,3);break; 22 | case 3:n=pow(10,4);break; 23 | case 4:printf("给出的数最大可以是多少?\n0~%d"); 24 | scanf("%d ",&maxnumber); 25 | while(maxnumber>0){ 26 | maxnumber/=10; 27 | t++; 28 | } n=pow(10,t);break; 29 | } 30 | srand( (unsigned)time( NULL ) ); 31 | number=rand()%n; 32 | printf("猜猜看是哪个数字\n"); 33 | do{ 34 | scanf("%d",&answer); 35 | fprintf(fp,"%d\n",answer); 36 | if(answer>number){ 37 | printf("猜大了,再来一次\n"); 38 | fprintf(fp,"猜大了,再来一次\n");} 39 | if(answer 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main(int argc, const char * argv[]) { 7 | int digits = 3; //初始化打印的随机数个数 8 | int tries = 1; 9 | int delay = 1; 10 | time_t wait_time = 0; 11 | int i = 0; 12 | time_t seed = 0; //随机函数种子值 13 | int number = 0; 14 | char another_game = 'Y'; 15 | do 16 | { 17 | bool correct = true; 18 | while(correct) 19 | { 20 | if(tries % 3 == 0 && tries != 3) 21 | digits++; 22 | 23 | srand((unsigned int)time(&seed)); 24 | for ( i = 1; i <= digits; i++ ) 25 | { 26 | printf("%d ",rand() % 10);//打印digits个随机数 27 | } 28 | fflush(stdout); 29 | wait_time = clock(); 30 | for(;clock() - wait_time < delay*CLOCKS_PER_SEC;);//等待3秒 31 | printf("\r");//返回行首 32 | for(i = 1; i <= digits;i++) 33 | { 34 | printf(" ");//清空原有的输出数字 35 | } 36 | printf("\r");//返回行首 37 | 38 | srand((unsigned int)seed); 39 | for(i = 1;i <= digits;i++) 40 | { 41 | // scanf("%*[^\n]"); 42 | // scanf("%*c");// 清空输入缓冲全数据 43 | scanf("%d",&number); 44 | if ( number != rand() % 10) 45 | { 46 | correct =false; 47 | break; 48 | } 49 | } 50 | printf("%s\n",correct ? "Correct!":"Wrong!");//返回结果 51 | tries++; 52 | } 53 | 54 | // fflush(stdin); 55 | scanf("%*[^\n]"); 56 | scanf("%*c"); 57 | printf("Another Game?\n"); 58 | scanf("%c",&another_game); 59 | }while(toupper(another_game)=='Y'); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /归并排序算法/mergesort.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/归并排序算法/mergesort.c -------------------------------------------------------------------------------- /得分排行/得分排行.c: -------------------------------------------------------------------------------- 1 | /* 2 | 得分排行 3 | 说明假设有一教师依学生座号输入考试分数,现希望在输入完毕后自动显示学生分数的排行, 4 | 当然学生的分数可能相同。 5 | 解法这个问题基本上要解不难,只要使用额外的一个排行阵列走访分数阵列就可以了,直接 6 | 使用下面的程式片段作说明: 7 | for(i = 0; i < count; i++) { 8 | juni[i] = 1; 9 | for(j = 0; j < count; j++) { 10 | if(score[j] > score[i]) 11 | juni[i]++; 12 | } 13 | } 14 | printf("得分\t排行\n"); 15 | for(i = 0; i < count; i++) 16 | printf("%d\t%d\n", score[i], juni[i]); 17 | 上面这个方法虽然简单,但是反覆计算的次数是n^2,如果n值变大,那么运算的时间就会拖长; 18 | 改变juni阵列的长度为n+2,并将初始值设定为0,如下所示: 19 | 接下来走访分数阵列,并在分数所对应的排行阵列索引元素上加1,如下所示: 20 | 将排行阵列最右边的元素设定为1,然后依序将右边的元素值加至左边一个元素,最后排行阵列 21 | 中的「分数+1」」就是得该分数的排行,如下所示: 22 | 这样的方式看起来复杂,其实不过在计算某分数之前排行的人数,假设89分之前的排行人数为x 23 | 人,则89分自然就是x+1了,这也是为什么排行阵列最右边要设定为1的原因;如果89分有y人, 24 | 则88分自然就是x+y+1,整个阵列右边元素向左加的原因正是如此。 25 | 如果分数有负分的情况,由于C/C++或Java等程式语言无法处理负的索引,所以必须加上一个 26 | 偏移值,将所有的分数先往右偏移一个范围即可,最后显示的时候记得减回偏移值就可以了。 27 | */ 28 | 29 | #include 30 | #include 31 | #define MAX 100 32 | #define MIN 0 33 | int main(void) { 34 | int score[MAX+1] = {0}; 35 | int juni[MAX+2] = {0}; 36 | int count = 0, i; 37 | do { 38 | printf("输入分数,-1结束:"); 39 | scanf("%d", &score[count++]); 40 | } while(score[count-1] != -1); 41 | count--; 42 | for(i = 0; i < count; i++) 43 | juni[score[i]]++; 44 | juni[MAX+1] = 1; 45 | for(i = MAX; i >= MIN; i--) 46 | juni[i] = juni[i] + juni[i+1]; 47 | printf("得分\t排行\n"); 48 | for(i = 0; i < count; i++) 49 | printf("%d\t%d\n", score[i], juni[score[i]+1]); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /循序搜寻法/循序搜寻法.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define MAX 10 5 | #define SWAP(x,y) {int t; t = x; x = y; y = t;} 6 | int search(int[]); 7 | int partition(int[], int, int); 8 | void quicksort(int[], int, int); 9 | int main(void) { 10 | int number[MAX+1] = {0}; 11 | int i, find; 12 | srand(time(NULL)); 13 | for(i = 1; i <= MAX; i++) 14 | number[i] = rand() % 100; 15 | quicksort(number, 1, MAX); 16 | printf("数列:"); 17 | for(i = 1; i <= MAX; i++) 18 | printf("%d ", number[i]); 19 | printf("\n输入搜寻值:"); 20 | scanf("%d", &number[0]); 21 | if(find = search(number)) 22 | printf("\n找到数值于索引 %d ", find); 23 | else 24 | printf("\n找不到数值"); 25 | printf("\n"); 26 | return 0; 27 | } 28 | 29 | int search(int number[]) { 30 | int i, k; 31 | k = number[0]; 32 | i = MAX; 33 | while(number[i] != k) 34 | i--; 35 | return i; 36 | } 37 | 38 | int partition(int number[], int left, int right) { 39 | int i, j, s; 40 | s = number[right]; 41 | i = left - 1; 42 | for(j = left; j < right; j++) { 43 | if(number[j] <= s) { 44 | i++; 45 | SWAP(number[i], number[j]); 46 | } 47 | } 48 | SWAP(number[i+1], number[right]); 49 | return i+1; 50 | } 51 | 52 | void quicksort(int number[], int left, int right) { 53 | int q; 54 | if(left < right) { 55 | q = partition(number, left, right); 56 | quicksort(number, left, q-1); 57 | quicksort(number, q+1, right); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /循环搜寻法/循序搜寻法.c: -------------------------------------------------------------------------------- 1 | /* 2 | 循序搜寻法(使用卫兵) 3 | 说明 4 | 搜寻的目的,是在「已排序的资料」中寻找指定的资料,而当中循序搜寻是最基本的搜寻法, 5 | 只要从资料开头寻找到最后,看看是否找到资料即可。 6 | 解法 7 | 初学者看到循序搜寻,多数都会使用以下的方式来进行搜寻: 8 | while(i < MAX) { 9 | if(number[i] == k) { 10 | printf("找到指定值"); 11 | break; 12 | } 13 | i++; 14 | } 15 | 这个方法基本上没有错,但是可以加以改善,可以利用设定卫兵的方式,省去if判断式,卫兵通 16 | 常设定在数列最后或是最前方,假设设定在列前方好了(索引0的位置),我们从数列后方向前 17 | 找,如果找到指定的资料时,其索引值不是0,表示在数列走访完之前就找到了,在程式的撰写 18 | 上,只要使用一个while回圈就可以了。 19 | 下面的程式为了配合卫兵的设置,自行使用快速排序法先将产生的数列排序,然后才进行搜寻, 20 | 若只是数字的话,通常您可以使用程式语言函式库所提供的搜寻函式。 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #define MAX 10 27 | #define SWAP(x,y) {int t; t = x; x = y; y = t;} 28 | int search(int[]); 29 | int partition(int[], int, int); 30 | void quicksort(int[], int, int); 31 | int main(void) { 32 | int number[MAX+1] = {0}; 33 | int i, find; 34 | srand(time(NULL)); 35 | for(i = 1; i <= MAX; i++) 36 | number[i] = rand() % 100; 37 | quicksort(number, 1, MAX); 38 | printf("数列:"); 39 | for(i = 1; i <= MAX; i++) 40 | printf("%d ", number[i]); 41 | printf("\n输入搜寻值:"); 42 | scanf("%d", &number[0]); 43 | if(find = search(number)) 44 | printf("\n找到数值于索引%d ", find); 45 | else 46 | printf("\n找不到数值"); 47 | printf("\n"); 48 | return 0; 49 | } 50 | int search(int number[]) { 51 | int i, k; 52 | k = number[0]; 53 | i = MAX; 54 | while(number[i] != k) 55 | i--; 56 | return i; 57 | } 58 | int partition(int number[], int left, int right) { 59 | int i, j, s; 60 | s = number[right]; 61 | i = left - 1; 62 | for(j = left; j < right; j++) { 63 | if(number[j] <= s) { 64 | i++; 65 | SWAP(number[i], number[j]); 66 | } 67 | } 68 | SWAP(number[i+1], number[right]); 69 | return i+1; 70 | } 71 | void quicksort(int number[], int left, int right) { 72 | int q; 73 | if(left < right) { 74 | q = partition(number, left, right); 75 | quicksort(number, left, q-1); 76 | quicksort(number, q+1, right); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /循环链表算法/README.md: -------------------------------------------------------------------------------- 1 | # list_x 2 | 循环链表 3 | -------------------------------------------------------------------------------- /循环链表算法/list_xzy.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/循环链表算法/list_xzy.c -------------------------------------------------------------------------------- /循环队列/循环队列.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define M_S 20 //定义数组长度,限制元素个数 4 | //定义结构体 5 | struct Queue 6 | { 7 | int a[M_S]; 8 | int front; //前指针,指向队首 9 | int rear; //后指针,指向对尾 10 | }; 11 | //初始化 12 | void InitQueue(struct Queue *p) 13 | { 14 | p->front=p->rear=0; //初始化前后指针都指向0 15 | } 16 | //求长度 17 | int QueueLength(struct Queue *p) 18 | { 19 | return (p->rear-p->front+M_S)%M_S; //求元素个数 20 | } 21 | //判断是否为空 22 | short IsEmpty(struct Queue *p) 23 | { 24 | if(p->front==p->rear) //若前后指针指向同一个节点,则判断为空 25 | return 1; 26 | else 27 | return 0; 28 | } 29 | //判断是否为满 30 | short IsFull(struct Queue *p) 31 | { 32 | if(p->front==(p->rear+1)%M_S) //若前指针等于(后指针+1)%数组大小,则判断为满 33 | return 1; 34 | else 35 | return 0; 36 | } 37 | //进队 38 | short EnQueue(struct Queue *p,int key) 39 | { 40 | if(IsFull(p)) //若队列为满,则进队失败 41 | return 0; 42 | p->a[p->rear]=key; //否则将进队元素赋值给后指针所指的位置,后指针往后移动一格 43 | p->rear=(p->rear+1)%M_S; 44 | return 1; 45 | } 46 | //出队 47 | short DeQueue(struct Queue *p,int *value) 48 | { 49 | if(IsEmpty(p)) //若队列为空,则出队失败 50 | return 0; 51 | *value=p->a[p->front]; //传入一个指针保留出队元素,然后队首指向下一个元素 52 | p->front=(p->front+1)%M_S; 53 | return 1; 54 | } 55 | int main() 56 | { 57 | struct Queue c; //定义结构体 58 | InitQueue(&c); //调用初始化函数,初始队列 59 | EnQueue(&c,1); //进队 60 | EnQueue(&c,2); 61 | EnQueue(&c,3); 62 | EnQueue(&c,4); 63 | int value; //出队,输出 64 | while(DeQueue(&c,&value)) 65 | { 66 | printf("---%d出队---还有%d人在队列---\n",value,QueueLength(&c)); 67 | sleep(1); 68 | } 69 | return 0; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /快速排序2/快速排序法(2).c: -------------------------------------------------------------------------------- 1 | /* 2 | 快速排序法(二) 3 | 说明在快速排序法(一)中,每次将最左边的元素设为轴,而之前曾经说过,快速排序法的 4 | 加速在于轴的选择,在这个例子中,只将轴设定为中间的元素,依这个元素作基准进行比较, 5 | 这可以增加快速排序法的效率。 6 | 解法在这个例子中,取中间的元素s作比较,同样的先得右找比s大的索引i,然后找比s小的 7 | 索引j,只要两边的索引还没有交会,就交换i 与j 的元素值,这次不用再进行轴的交换了, 8 | 因为在寻找交换的过程中,轴位置的元素也会参与交换的动作,例如: 9 | 41 24 76 11 45 64 21 69 19 36 10 | 首先left为0,right为9,(left+right)/2 = 4(取整数的商),所以轴为索引4的位置,比较的元素是 11 | 45,您往右找比45大的,往左找比45小的进行交换: 12 | 41 24 76* 11 [45] 64 21 69 19 *36 13 | 41 24 36 11 45* 64 21 69 19* 76 14 | 41 24 36 11 19 64* 21* 69 45 76 15 | [41 24 36 11 19 21] [64 69 45 76] 16 | 完成以上之后,再初别对左边括号与右边括号的部份进行递回,如此就可以完成排序的目的。 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #define MAX 10 23 | #define SWAP(x,y) {int t; t = x; x = y; y = t;} 24 | void quicksort(int[], int, int); 25 | int main(void) { 26 | int number[MAX] = {0}; 27 | int i, num; 28 | srand(time(NULL)); 29 | printf("排序前:"); 30 | for(i = 0; i < MAX; i++) { 31 | number[i] = rand() % 100; 32 | printf("%d ", number[i]); 33 | } 34 | quicksort(number, 0, MAX-1); 35 | printf("\n排序后:"); 36 | for(i = 0; i < MAX; i++) 37 | printf("%d ", number[i]); 38 | printf("\n"); 39 | return 0; 40 | } 41 | void quicksort(int number[], int left, int right) { 42 | int i, j, s; 43 | if(left < right) { 44 | s = number[(left+right)/2]; 45 | i = left - 1; 46 | j = right + 1; 47 | while(1) { 48 | while(number[++i] < s) ; // 向右找 49 | while(number[--j] > s) ; // 向左找 50 | if(i >= j) 51 | break; 52 | SWAP(number[i], number[j]); 53 | } 54 | quicksort(number, left, i-1); // 对左边进行递回 55 | quicksort(number, j+1, right); // 对右边进行递回 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /快速排序3/快速排序法(3).c: -------------------------------------------------------------------------------- 1 | /* 2 | 快速排序法(三) 3 | 说明 4 | 之前说过轴的选择是快速排序法的效率关键之一,在这边的快速排序法的轴选择方式更加快了 5 | 快速排序法的效率,它是来自演算法名书Introduction to Algorithms 之中。 6 | 解法 7 | 先说明这个快速排序法的概念,它以最右边的值s作比较的标准,将整个数列分为三个部份, 8 | 一个是小于s的部份,一个是大于s的部份,一个是未处理的部份,如下所示: 9 | 在排序的过程中,i 与j 都会不断的往右进行比较与交换,最后数列会变为以下的状态: 10 | 然后将s的值置于中间,接下来就以相同的步骤会左右两边的数列进行排序的动作,如下所示: 11 | 整个演算的过程,直接摘录书中的虚拟码来作说明: 12 | QUICKSORT(A, p, r) 13 | if p < r 14 | then q <- PARTITION(A, p, r) 15 | QUICKSORT(A, p, q-1) 16 | QUICKSORT(A, q+1, r) 17 | end QUICKSORT 18 | PARTITION(A, p, r) 19 | x <- A[r] 20 | i <- p-1 21 | for j <- p to r-1 22 | do if A[j] <= x 23 | then i <- i+1 24 | exchange A[i]<->A[j] 25 | exchange A[i+1]<->A[r] 26 | return i+1 27 | end PARTITION 28 | 一个实际例子的演算如下所示: 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #define MAX 10 35 | #define SWAP(x,y) {int t; t = x; x = y; y = t;} 36 | int partition(int[], int, int); 37 | void quicksort(int[], int, int); 38 | int main(void) { 39 | int number[MAX] = {0}; 40 | int i, num; 41 | srand(time(NULL)); 42 | printf("排序前:"); 43 | for(i = 0; i < MAX; i++) { 44 | number[i] = rand() % 100; 45 | printf("%d ", number[i]); 46 | } 47 | quicksort(number, 0, MAX-1); 48 | printf("\n排序后:"); 49 | for(i = 0; i < MAX; i++) 50 | printf("%d ", number[i]); 51 | printf("\n"); 52 | return 0; 53 | } 54 | int partition(int number[], int left, int right) { 55 | int i, j, s; 56 | s = number[right]; 57 | i = left - 1; 58 | for(j = left; j < right; j++) { 59 | if(number[j] <= s) { 60 | i++; 61 | SWAP(number[i], number[j]); 62 | } 63 | } 64 | SWAP(number[i+1], number[right]); 65 | return i+1; 66 | } 67 | void quicksort(int number[], int left, int right) { 68 | int q; 69 | if(left < right) { 70 | q = partition(number, left, right); 71 | quicksort(number, left, q-1); 72 | quicksort(number, q+1, right); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /快速排序算法/quick_sort.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/快速排序算法/quick_sort.c -------------------------------------------------------------------------------- /排列组合/排列组合.c: -------------------------------------------------------------------------------- 1 | /* 2 | 排列组合 3 | 说明将一组数字、字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的排列 4 | 组合有:1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1。 5 | 解法可以使用递回将问题切割为较小的单元进行排列组合,例如1 2 3 4的排列可以分为1 [2 3 6 | 4]、2 [1 3 4]、3 [1 2 4]、4 [1 2 3]进行排列,这边利用旋转法,先将旋转间隔设为0,将最右边的 7 | 数字旋转至最左边,并逐步增加旋转的间隔, 8 | */ 9 | 10 | #include 11 | #include 12 | #define N 4 13 | void perm(int*, int); 14 | int main(void) { 15 | int num[N+1], i; 16 | for(i = 1; i <= N; i++) 17 | num[i] = i; 18 | perm(num, 1); 19 | return 0; 20 | } 21 | void perm(int* num, int i) { 22 | int j, k, tmp; 23 | if(i < N) { 24 | for(j = i; j <= N; j++) { 25 | tmp = num[j]; 26 | // 旋转该区段最右边数字至最左边 27 | for(k = j; k > i; k--) 28 | num[k] = num[k-1]; 29 | num[i] = tmp; 30 | perm(num, i+1); 31 | // 还原 32 | for(k = i; k < j; k++) 33 | num[k] = num[k+1]; 34 | num[j] = tmp; 35 | } 36 | } 37 | else { // 显示此次排列 38 | for(j = 1; j <= N; j++) 39 | printf("%d ", num[j]); 40 | printf("\n"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /推荐算法/流行度推荐算法/流行度推荐算法.java: -------------------------------------------------------------------------------- 1 | //一次点击率可以增加的得分 2 | private static int READ_COUNT_K = 1; 3 | //一次点赞增加的评分 4 | private static int LIKE_COUNT_K = 3; 5 | 6 | public double calculateHackerNewsScore(Article article) 7 | { 8 | String updateTime = article.getUpdateTime(); 9 | int readCount = article.getReadCount(); 10 | int likeCount = article.getLikeCount(); 11 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 12 | Date date = null; 13 | try { 14 | date = formatter.parse(updateTime); 15 | } catch (ParseException e) { 16 | date = new Date(); 17 | } 18 | 19 | //发帖时间的时间戳 20 | double updateTimeStamp = date.getTime() ; 21 | System.out.println("发帖时间的时间戳"+updateTimeStamp); 22 | //当前时间的时间戳 23 | double nowTimeStamp = System.currentTimeMillis(); 24 | System.out.println("当前时间的时间戳"+nowTimeStamp); 25 | //用来获取两个时间相差的毫秒数 26 | double l=nowTimeStamp -updateTimeStamp; 27 | 28 | //相差的天 29 | double day=l/(24*60*60*1000); 30 | //相差的小时 31 | double hour=(day*24); 32 | 33 | double week = day/7; 34 | double month = week/4; 35 | /** 36 | * HackerNews评分 分子 点击权重为1 点赞权重为3 分母为 距离发帖时间相差的时间+2的G次方 37 | */ 38 | double score = ((readCount *READ_COUNT_K + likeCount *LIKE_COUNT_K) -1)/Math.pow((week +2),G); 39 | score *= 10000; 40 | System.out.println("文章" +article.getId() +" 发帖时间为" +updateTime +" 与当前时间相差" + week +"星期 评分为"+score); 41 | return score; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /推荐算法/混合推荐算法/混合推荐算法.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /插值查找/插值查找.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | //插值查找法 arr数组,length 数组长度,key 查找的关键字 4 | //返回查找值的下标 ,没查找到 返回-1 5 | int Interpolation_Search(int *arr, int length, int key) 6 | { 7 | int low = 0;//低位下标 8 | int high = length-1;//高位下标 9 | int mid;//中间值下标 10 | while (low <= high) 11 | { 12 | mid = (high-low)*(key - arr[low]) / (arr[high] - arr[low]);//插值 13 | if (key < arr[mid]) 14 | { 15 | high = mid - 1; 16 | } 17 | else if(key > arr[mid]) 18 | { 19 | low = mid + 1; 20 | } 21 | else 22 | { 23 | return mid; 24 | } 25 | } 26 | return -1; 27 | } 28 | int main(int argc, char *argv[]) 29 | { 30 | int arr[10] = { 0,1,2,3,4,5,6,7,8,9}; 31 | int index1 = Interpolation_Search(arr, 10, 5); 32 | int index2 = Interpolation_Search(arr, 10, 100); 33 | printf("index1 = %d,index2 = %d\n",index1,index2); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /插入排序算法/InsertSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 插入排序算法 3 | * create by JackChen 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | void insertsort(int arr[],int nlenght) 10 | { 11 | int i,j; 12 | int ptemp; 13 | for(i = 0;iptemp && j>=0) 18 | { 19 | arr[j+1] = arr[j]; 20 | j--; 21 | } 22 | arr[j+1] = ptemp; 23 | 24 | } 25 | 26 | 27 | } 28 | 29 | void print(int arr[], int nlenght) 30 | { 31 | int i; 32 | for(i = 0;i 7 | #include 8 | #include 9 | #define MAX 10 10 | #define SWAP(x,y) {int t; t = x; x = y; y = t;} 11 | void quicksort(int[], int, int); 12 | int intsrch(int[], int); 13 | int main(void) { 14 | int number[MAX] = {0}; 15 | int i, find; 16 | srand(time(NULL)); 17 | for(i = 0; i < MAX; i++) { 18 | number[i] = rand() % 100; 19 | } 20 | quicksort(number, 0, MAX-1); 21 | printf("数列:"); 22 | for(i = 0; i < MAX; i++) 23 | printf("%d ", number[i]); 24 | printf("\n输入寻找对象:"); 25 | scanf("%d", &find); 26 | if((i = intsrch(number, find)) >= 0) 27 | printf("找到数字于索引%d ", i); 28 | else 29 | printf("\n找不到指定数"); 30 | printf("\n"); 31 | return 0; 32 | } 33 | int intsrch(int number[], int find) { 34 | int low, mid, upper; 35 | low = 0; 36 | upper = MAX - 1; 37 | while(low <= upper) { 38 | mid = (upper-low)* 39 | (find-number[low])/(number[upper]-number[low]) 40 | + low; 41 | if(mid < low || mid > upper) 42 | return -1; 43 | if(find < number[mid]) 44 | upper = mid - 1; 45 | else if(find > number[mid]) 46 | low = mid + 1; 47 | else 48 | return mid; 49 | } 50 | return -1; 51 | } 52 | void quicksort(int number[], int left, int right) { 53 | int i, j, k, s; 54 | if(left < right) { 55 | s = number[(left+right)/2]; 56 | i = left - 1; 57 | j = right + 1; 58 | while(1) { 59 | while(number[++i] < s) ; 60 | while(number[--j] > s) ; 61 | if(i >= j) 62 | break; 63 | SWAP(number[i], number[j]); 64 | } 65 | quicksort(number, left, i-1); 66 | quicksort(number, j+1, right); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /斐波那契堆/fibonacci_heap.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIBONACCI_HEAP_H_ 2 | #define _FIBONACCI_HEAP_H_ 3 | 4 | typedef int Type; 5 | 6 | typedef struct _FibonacciNode 7 | { 8 | Type key; // 关键字(键值) 9 | int degree; // 度数 10 | struct _FibonacciNode *left; // 左兄弟 11 | struct _FibonacciNode *right; // 右兄弟 12 | struct _FibonacciNode *child; // 第一个孩子节点 13 | struct _FibonacciNode *parent; // 父节点 14 | int marked; //是否被删除第1个孩子(1表示删除,0表示未删除) 15 | }FibonacciNode, FibNode; 16 | 17 | typedef struct _FibonacciHeap{ 18 | int keyNum; // 堆中节点的总数 19 | int maxDegree; // 最大度 20 | struct _FibonacciNode *min; // 最小节点(某个最小堆的根节点) 21 | struct _FibonacciNode **cons; // 最大度的内存区域 22 | }FibonacciHeap, FibHeap; 23 | 24 | // 创建Fibonacci堆 25 | FibHeap* fib_heap_make(); 26 | // 新建键值为key的节点,并将其插入到斐波那契堆中 27 | void fib_heap_insert_key(FibHeap *heap, Type key); 28 | // 删除键值为key的结点 29 | void fib_heap_delete(FibHeap *heap, Type key); 30 | // 移除最小节点 31 | void fib_heap_extract_min(FibHeap *heap); 32 | // 更新heap的中的oldkey为newkey 33 | void fib_heap_update(FibHeap *heap, Type oldkey, Type newkey); 34 | // 将h1, h2合并成一个堆,并返回合并后的堆 35 | FibHeap* fib_heap_union(FibHeap *h1, FibHeap *h2); 36 | // 在斐波那契堆heap中是否存在键值为key的节点;存在返回1,否则返回0。 37 | int fib_heap_contains(FibHeap *heap, Type key); 38 | // 获取最小节点对应的值(保存在pkey中);成功返回1,失败返回0。 39 | int fib_heap_get_min(FibHeap *heap, Type *pkey); 40 | // 销毁斐波那契堆 41 | void fib_heap_destroy(FibHeap *heap); 42 | // 打印"斐波那契堆" 43 | void fib_print(FibHeap *heap); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /斐波那契查找/斐波那契查找.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define FIB_MAXSIZE 100 4 | 5 | /** 6 | * 生成斐波那契数列 7 | * @param fib:指向存储斐波那契数列的数组的指针 8 | * @param size:斐波那契数列长度 9 | */ 10 | void ProduceFib(int *fib, int size) 11 | { 12 | int i; 13 | 14 | fib[0] = 1; 15 | fib[1] = 1; 16 | 17 | for (i = 2; i < size; i++) 18 | { 19 | fib[i] = fib[i - 1] + fib[i - 2]; 20 | } 21 | } 22 | 23 | /** 24 | * 斐波那契查找,查找成功返回位序,否则返回-1 25 | * @param data:有序表数组 26 | * @param length:有序表元素个数 27 | * @param searchValue:待查找关键字 28 | */ 29 | int FibonacciSearch(int *data, int length, int searchValue) 30 | { 31 | int low, high, mid, k, i, fib[FIB_MAXSIZE]; 32 | 33 | low = 0; 34 | high = length - 1; 35 | 36 | ProduceFib(fib, FIB_MAXSIZE); 37 | 38 | k = 0; 39 | // 找到有序表元素个数在斐波那契数列中最接近的最大数列值 40 | while (high > fib[k] - 1) 41 | { 42 | k++; 43 | } 44 | 45 | // 补齐有序表 46 | for (i = length; i <= fib[k] - 1; i++) 47 | { 48 | data[i] = data[high]; 49 | } 50 | 51 | while (low <= high) 52 | { 53 | mid = low + fib[k - 1] - 1; // 根据斐波那契数列进行黄金分割 54 | 55 | if (data[mid] == searchValue) 56 | { 57 | if (mid <= length - 1) 58 | { 59 | return mid; 60 | } 61 | else 62 | { 63 | // 说明查找得到的数据元素是补全值 64 | return length - 1; 65 | } 66 | } 67 | 68 | if (data[mid] > searchValue) 69 | { 70 | high = mid - 1; 71 | k = k - 1; 72 | } 73 | 74 | if (data[mid] < searchValue) 75 | { 76 | low = mid + 1; 77 | k = k - 2; 78 | } 79 | } 80 | 81 | return -1; 82 | } 83 | 84 | int main() 85 | { 86 | int data[] = {1,3,5,7,9,11,13,15,17,19,21}; 87 | 88 | int index = FibonacciSearch(data, 11, 19); 89 | printf("%d\n", index); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /斜堆/skewheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _SKEW_HEAP_H_ 2 | #define _SKEW_HEAP_H_ 3 | 4 | typedef int Type; 5 | 6 | typedef struct _SkewNode{ 7 | Type key; // 关键字(键值) 8 | struct _SkewNode *left; // 左孩子 9 | struct _SkewNode *right; // 右孩子 10 | }SkewNode, *SkewHeap; 11 | 12 | // 前序遍历"斜堆" 13 | void preorder_skewheap(SkewHeap heap); 14 | // 中序遍历"斜堆" 15 | void inorder_skewheap(SkewHeap heap); 16 | // 后序遍历"斜堆" 17 | void postorder_skewheap(SkewHeap heap); 18 | 19 | // 获取最小值(保存到pval中),成功返回0,失败返回-1。 20 | int skewheap_minimum(SkewHeap heap, int *pval); 21 | // 合并"斜堆x"和"斜堆y",并返回合并后的新树 22 | SkewNode* merge_skewheap(SkewHeap x, SkewHeap y); 23 | // 将结点插入到斜堆中,并返回根节点 24 | SkewNode* insert_skewheap(SkewHeap heap, Type key); 25 | // 删除结点(key为节点的值),并返回根节点 26 | SkewNode* delete_skewheap(SkewHeap heap); 27 | 28 | // 销毁斜堆 29 | void destroy_skewheap(SkewHeap heap); 30 | 31 | // 打印斜堆 32 | void print_skewheap(SkewHeap heap); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /斜堆/skewheap_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "skewheap.h" 3 | 4 | #define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) ) 5 | 6 | void main() 7 | { 8 | int i; 9 | int a[]= {10,40,24,30,36,20,12,16}; 10 | int b[]= {17,13,11,15,19,21,23}; 11 | int alen=LENGTH(a); 12 | int blen=LENGTH(b); 13 | SkewHeap ha,hb; 14 | 15 | ha=hb=NULL; 16 | 17 | printf("== 斜堆(ha)中依次添加: "); 18 | for(i=0; i 3 | #include 4 | 5 | int MaxSum(int m, int n, int *a); 6 | 7 | int main() 8 | { 9 | int a[] = { 0, 2, 3, -7, 6, 4, -5 }; 10 | for (int i = 1; i <= 6; i++) 11 | { 12 | printf("%d ", a[i]); 13 | } 14 | printf("\n"); 15 | printf("数组a的最大连续子段和为:%d\n", MaxSum(3, 6, a)); 16 | } 17 | 18 | int MaxSum(int m, int n, int *a) 19 | { 20 | if (nc[j - 1] ? b[j - 1] + a[j] : c[j - 1] + a[j]; 35 | c[j - 1] = max;//预先保存第j-1行的最大j-1子段和 36 | if (max 3 | 4 | int MaxSum(int n, int *a, int *besti, int *bestj); 5 | 6 | int main() 7 | { 8 | int a[] = { -2, 11, -4, 13, -5, -2 }; 9 | for (int i = 0; i<6; i++) 10 | { 11 | printf("%d ", a[i]); 12 | } 13 | int besti, bestj; 14 | printf("\n"); 15 | printf("数组a的最大连续子段和为:a[%d:%d]:%d\n", besti, bestj, MaxSum(6, a, &besti, &bestj)); 16 | return 0; 17 | } 18 | 19 | int MaxSum(int n, int *a, int *besti, int *bestj) 20 | { 21 | int sum = 0; 22 | for (int i = 0; isum) 32 | { 33 | sum = thissum; 34 | *besti = i; 35 | *bestj = j; 36 | } 37 | } 38 | } 39 | return sum; 40 | } -------------------------------------------------------------------------------- /最大访客数/最大访客数.c: -------------------------------------------------------------------------------- 1 | /* 2 | 最大访客数 3 | */ 4 | 5 | #include 6 | #include 7 | #define MAX 100 8 | #define SWAP(x,y) {int t; t = x; x = y; y = t;} 9 | int partition(int[], int, int); 10 | void quicksort(int[], int, int); 11 | int maxguest(int[], int[], int, int); 12 | int main(void) { 13 | int x[MAX] = {0}; 14 | int y[MAX] = {0}; 15 | int time = 0; 16 | int count = 0; 17 | printf("\n输入来访与离开125;时间(0~24):"); 18 | printf("\n范例:10 15"); 19 | printf("\n输入-1 -1结束"); 20 | while(count < MAX) { 21 | printf("\n>>"); 22 | scanf("%d %d", &x[count], &y[count]); 23 | if(x[count] < 0) 24 | break; 25 | count++; 26 | } 27 | if(count >= MAX) { 28 | printf("\n超出最大访客数(%d)", MAX); 29 | count--; 30 | } 31 | 32 | quicksort(x, 0, count); 33 | quicksort(y, 0, count); 34 | while(time < 25) { 35 | printf("\n%d 时的最大访客数:%d", 36 | time, maxguest(x, y, count, time)); 37 | time++; 38 | } 39 | printf("\n"); 40 | return 0; 41 | } 42 | int maxguest(int x[], int y[], int count, int time) { 43 | int i, num = 0; 44 | for(i = 0; i <= count; i++) { 45 | if(time > x[i]) 46 | num++; 47 | if(time > y[i]) 48 | num--; 49 | } 50 | return num; 51 | } 52 | int partition(int number[], int left, int right) { 53 | int i, j, s; 54 | s = number[right]; 55 | i = left - 1; 56 | for(j = left; j < right; j++) { 57 | if(number[j] <= s) { 58 | i++; 59 | SWAP(number[i], number[j]); 60 | } 61 | } 62 | SWAP(number[i+1], number[right]); 63 | return i+1; 64 | } 65 | void quicksort(int number[], int left, int right) { 66 | int q; 67 | if(left < right) { 68 | q = partition(number, left, right); 69 | quicksort(number, left, q-1); 70 | quicksort(number, q+1, right); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /最小生成树/Kruskal.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /最小生成树/Prime.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/最小生成树/Prime.c -------------------------------------------------------------------------------- /最短路径算法/最短路径算法.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /最长公共子序列问题/最长公共子序列问题.c: -------------------------------------------------------------------------------- 1 | // 最长公共子序列问题 2 | #include 3 | 4 | const int M = 7; 5 | const int N = 6; 6 | void output(char *s, int n); 7 | void LCSLength(int m, int n, char *x, char *y, int **c, int **b); 8 | void LCS(int i, int j, char *x, int **b); 9 | 10 | int main() 11 | { 12 | 13 | char x[] = { ' ', 'A', 'B', 'C', 'B', 'D', 'A', 'B' }; 14 | char y[] = { ' ', 'B', 'D', 'C', 'A', 'B', 'A' }; 15 | 16 | int **c = (int**)malloc((M + 1)*sizeof(int*)); 17 | int **b = (int**)malloc((M + 1)*sizeof(int*)); 18 | for (int i = 0; i <= M; i++){ 19 | c[i] = (int*)malloc((N + 1)*sizeof(int)); 20 | b[i] = (int*)malloc((N + 1)*sizeof(int)); 21 | } 22 | printf("序列X:\n"); 23 | output(x, M); 24 | printf("序列Y:\n"); 25 | output(y, N); 26 | LCSLength(M, N, x, y, c, b); 27 | printf("序列X、Y最长公共子序列长度为:%d\n", c[M][N]); 28 | printf("序列X、Y最长公共子序列为:\n"); 29 | LCS(M, N, x, b); 30 | printf("\n"); 31 | } 32 | 33 | void output(char *s, int n) 34 | { 35 | for (int i = 1; i <= n; i++) 36 | { 37 | printf("%c ", s[i]); 38 | } 39 | printf("\n"); 40 | } 41 | 42 | void LCSLength(int m, int n, char *x, char *y, int **c, int **b) 43 | { 44 | int i, j; 45 | for (i = 1; i <= m; i++) 46 | c[i][0] = 0; 47 | for (i = 1; i <= n; i++) 48 | c[0][i] = 0; 49 | for (i = 1; i <= m; i++) 50 | { 51 | for (j = 1; j <= n; j++) 52 | { 53 | if (x[i] == y[j]) 54 | { 55 | c[i][j] = c[i - 1][j - 1] + 1; 56 | b[i][j] = 1; 57 | } 58 | else if (c[i - 1][j] >= c[i][j - 1]) 59 | { 60 | c[i][j] = c[i - 1][j]; 61 | b[i][j] = 2; 62 | } 63 | else 64 | { 65 | c[i][j] = c[i][j - 1]; 66 | b[i][j] = 3; 67 | } 68 | } 69 | } 70 | } 71 | 72 | void LCS(int i, int j, char *x, int **b) 73 | { 74 | if (i == 0 || j == 0) 75 | { 76 | return; 77 | } 78 | if (b[i][j] == 1) 79 | { 80 | LCS(i - 1, j - 1, x, b); 81 | printf("%c ", x[i]); 82 | } 83 | else if (b[i][j] == 2) 84 | { 85 | LCS(i - 1, j, x, b); 86 | } 87 | else 88 | { 89 | LCS(i, j - 1, x, b); 90 | } 91 | } -------------------------------------------------------------------------------- /朴素贝叶斯算法/贝叶斯.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /树表查找/biTree.h: -------------------------------------------------------------------------------- 1 | #ifndef CHIYX_BITREE 2 | #define CHIYX_BITREE 3 | #ifndef NULL 4 | #define NULL 0 5 | #endif 6 | 7 | typedef int DataType; 8 | //二叉树的节点结构 9 | typedef struct BiTreeNode { 10 | DataType data; 11 | struct BiTreeNode *parent; 12 | struct BiTreeNode *left; 13 | struct BiTreeNode *right; 14 | }BiTreeNode, *BiTree; 15 | 16 | //查找:返回第一个等于data域等于key的节点,不存在返回NULL 17 | BiTreeNode *search(BiTree *biTree, DataType key); 18 | //返回二叉树的最小节点,空树返回NULL 19 | BiTreeNode *minImum(BiTree *biTree); 20 | //返回二叉树的最大节点,空树返回NULL 21 | BiTreeNode *maxImum(BiTree *biTree); 22 | //返回节点x的后继节点,不存在后继(节点x为最大节点)返回NULL 23 | BiTreeNode *successor(BiTreeNode *x); 24 | //返回节点x的前驱节点,不存在前驱(节点x为最小节点)返回NULL 25 | BiTreeNode *predecessor(BiTreeNode *x); 26 | //将值data插入到二叉树中(生成一个值为data的节点) 27 | void insertNode(BiTree *biTree, DataType data); 28 | //删除一个值为data的节点 29 | void deleteNode(BiTree *biTree, DataType data); 30 | //中序遍历二叉树 31 | void inorderTraversal(BiTree *biTree, void (*visitor)(BiTreeNode *node)); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /树表查找/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "biTree.h" 4 | #define N 10 5 | void printNode(BiTreeNode *node); 6 | 7 | int main(int argc, char *argv[]) { 8 | BiTreeNode *root; 9 | int i; 10 | 11 | root = NULL; 12 | int data[N] = {10, 23, 11, 98, 111, 87, 34, 11, 33, 8}; 13 | for (i = 0; i < N; i++) { 14 | insertNode(&root, data[i]); 15 | } 16 | printf("before delete:\n"); 17 | inorderTraversal(&root, printNode); 18 | printf("\n"); 19 | deleteNode(&root, 11); 20 | deleteNode(&root, 8); 21 | printf("after delete:\n"); 22 | inorderTraversal(&root, printNode); 23 | printf("\n"); 24 | exit(0); 25 | } 26 | void printNode(BiTreeNode *node) { 27 | printf("%d\t", node->data); 28 | } 29 | -------------------------------------------------------------------------------- /格雷码/格雷码.c: -------------------------------------------------------------------------------- 1 | /* 2 | 格雷码(Gray Code) 3 | 说明 4 | Gray Code是一个数列集合,每个数使用二进位来表示,假设使用n位元来表示每个数好了,任 5 | 两个数之间只有一个位元值不同,例如以下为3位元的Gray Code: 6 | 000 001 011 010 110 111 101 100 7 | 由定义可以知道,Gray Code的顺序并不是唯一的,例如将上面的数列反过来写,也是一组Gray 8 | Code: 9 | 100 101 111 110 010 011 001 000 10 | Gray Code是由贝尔实验室的Frank Gray在1940年代提出的,用来在使用PCM(Pusle Code 11 | Modulation)方法传送讯号时避免出错,并于1953年三月十七日取得美国专利。 12 | 解法 13 | 由于Gray Code相邻两数之间只改变一个位元,所以可观察Gray Code从1变0或从0变1时的 14 | 位置,假设有4位元的Gray Code如下: 15 | 0000 0001 0011 0010 0110 0111 0101 0100 16 | 1100 1101 1111 1110 1010 1011 1001 1000 17 | 观察奇数项的变化时,我们发现无论它是第几个Gray Code,永远只改变最右边的位元,如果 18 | 是1就改为0,如果是0就改为1。 19 | 观察偶数项的变化时,我们发现所改变的位元,是由右边算来第一个1的左边位元。 20 | 以上两个变化规则是固定的,无论位元数为何;所以只要判断位元的位置是奇数还是偶数,就 21 | 可以决定要改变哪一个位元的值,为了程式撰写方便,将阵列索引0当作最右边的值,而在列 22 | 印结果时,是由索引数字大的开始反向列印。 23 | 将2位元的Gray Code当作平面座标来看,可以构成一个四边形,您可以发现从任一顶点出发, 24 | 绕四边形周长绕一圈,所经过的顶点座标就是一组Gray Code,所以您可以得到四组Gray 25 | Code。 26 | 同样的将3位元的Gray Code当作平面座标来看的话,可以构成一个正立方体,如果您可以从任 27 | 一顶点出发,将所有的边长走过,并不重复经过顶点的话,所经过的顶点座标顺序之组合也就 28 | 是一组Gray Code。 29 | */ 30 | 31 | #include 32 | #include 33 | #define MAXBIT 20 34 | #define TRUE 1 35 | #define CHANGE_BIT(x) x = ((x) == '0' ? '1' : '0') 36 | #define NEXT(x) x = (1 - (x)) 37 | int main(void) { 38 | char digit[MAXBIT]; 39 | int i, bits, odd; 40 | printf("输入位元数:"); 41 | scanf("%d", &bits); 42 | for(i = 0; i < bits; i++) { 43 | digit[i] = '0'; 44 | printf("0"); 45 | } 46 | printf("\n"); 47 | odd = TRUE; 48 | while(1) { 49 | if(odd) 50 | CHANGE_BIT(digit[0]); 51 | else { 52 | // 计算第一个1的位置 53 | for(i = 0; i < bits && digit[i] == '0'; i++) ; 54 | if(i == bits - 1) // 最后一个Gray Code 55 | break; 56 | CHANGE_BIT(digit[i+1]); 57 | } 58 | for(i = bits - 1; i >= 0; i--) 59 | printf("%c", digit[i]); 60 | printf("\n"); 61 | NEXT(odd); 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /桶排序/bin_sort_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define MAX_NUMBER 100000 6 | using namespace std; 7 | typedef struct node 8 | { 9 | int m_nkey; 10 | node * m_pnext; 11 | }; 12 | void bin_sort(int * a,int size,int bucket_size) 13 | { 14 | node ** node_table=new node*[bucket_size]; 15 | for (int i=0;im_nkey=0; 19 | node_table[i]->m_pnext=NULL; 20 | } 21 | for (int i=0;im_nkey=a[i]; 25 | pNode->m_pnext=NULL; 26 | int index=a[i]/bucket_size; 27 | if (node_table[index]->m_nkey==0) 28 | { 29 | node_table[index]->m_nkey++; 30 | node_table[index]->m_pnext=pNode; 31 | } 32 | else 33 | { 34 | node *pTmep=node_table[index]->m_pnext; 35 | while(pTmep->m_pnext!=NULL&&pTmep->m_pnext->m_nkeym_pnext; 37 | node *pNext=pTmep->m_pnext;//插入 38 | pTmep->m_pnext=pNode; 39 | pNode->m_pnext=pNext; 40 | node_table[index]->m_nkey++; 41 | } 42 | } 43 | for (int i=0;im_pnext; 46 | while(p!=NULL) 47 | { 48 | cout<m_nkey<<" "; 49 | p=p->m_pnext; 50 | } 51 | } 52 | for (int i=0;im_pnext; 55 | while(p!=NULL) 56 | { 57 | node *next=p->m_pnext; 58 | delete p; 59 | p=next; 60 | } 61 | p=NULL; 62 | } 63 | } 64 | int main() 65 | { 66 | ofstream out("test.txt",ofstream::out|ofstream::app); 67 | 68 | srand(time(NULL)); 69 | for (int i=0;i<100000000;i++) 70 | { 71 | int a=rand()%100000; 72 | out<>a[i]; 79 | } 80 | bin_sort(a,MAX_NUMBER,1000); 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /模拟退火算法/模拟退火算法.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | //#pragma comment(linker, "/STACK:1024000000,1024000000"); 12 | 13 | using namespace std; 14 | 15 | #define INF 0x3f3f3f3f 16 | 17 | double y; 18 | 19 | double getsum(double x) 20 | { 21 | return 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-y*x; 22 | } 23 | 24 | int main() 25 | { 26 | int T; 27 | scanf("%d",&T); 28 | while(T--) 29 | { 30 | scanf("%lf",&y); 31 | double delte=0.98; 32 | double t=100; 33 | double x=0; 34 | double ans=getsum(x); 35 | while(t>1e-8) 36 | { 37 | int flag=1; 38 | while(flag) 39 | { 40 | flag=0; 41 | double temp=x+t; 42 | if(temp>=0&&temp<=100&&getsum(temp)=1e-8) 43 | { 44 | x=temp; 45 | ans=getsum(temp); 46 | flag=1; 47 | } 48 | temp=x-t; 49 | if(temp>=0&&temp<=100&&getsum(temp)=1e-8) 50 | { 51 | x=temp; 52 | ans=getsum(temp); 53 | flag=1; 54 | } 55 | } 56 | t*=delte; 57 | } 58 | printf("%.4f\n",ans); 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /河内之塔/Hanoi.c: -------------------------------------------------------------------------------- 1 | /* 2 | 河内之塔 3 | */ 4 | 5 | #include 6 | void hanoi(int n, char A, char B, char C) { 7 | if(n == 1) { 8 | printf("Move sheet %d from %c to %c\n", n, A, C); 9 | } 10 | else { 11 | hanoi(n-1, A, C, B); 12 | printf("Move sheet %d from %c to %c\n", n, A, C); 13 | hanoi(n-1, B, A, C); 14 | } 15 | } 16 | int main() { 17 | int n; 18 | printf("请输入盘数:"); 19 | scanf("%d", &n); 20 | hanoi(n, 'A', 'B', 'C'); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /游戏/Tennis/README.md: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /游戏/忍者神龟/README.md: -------------------------------------------------------------------------------- 1 | # 2 | ![image](https://user-images.githubusercontent.com/87458342/128980844-7a6f6354-195f-49d7-8cf6-a382625902d4.png) 3 | -------------------------------------------------------------------------------- /游戏/超级玛丽/README.md: -------------------------------------------------------------------------------- 1 | # Super Mario Bros themed T-Watch Firmware 2 | 3 | ![image](https://user-images.githubusercontent.com/87458342/128981330-a7f36871-731a-4964-83d3-febce8c8cc4f.png) 4 | 5 | [Github address](https://github.com/wizche/ttgo-smb) 6 | -------------------------------------------------------------------------------- /游戏/魂斗罗/README.md: -------------------------------------------------------------------------------- 1 | # 2 | ![image](https://user-images.githubusercontent.com/87458342/128980762-5013dccb-d869-44da-911e-ad847568e34a.png) 3 | -------------------------------------------------------------------------------- /滑动窗口算法/滑动窗口.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /爬山算法/爬山算法.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define N 10010 7 | #define eps 1e-8 8 | #define pro 0.97 9 | 10 | using namespace std; 11 | int n; 12 | struct Point 13 | { 14 | double x,y; 15 | friend ostream& operator << (ostream &_,Point a) 16 | { 17 | printf("%.3lf %.3lf\n",a.x,a.y); 18 | return _; 19 | } 20 | Point(){} 21 | Point(double _x,double _y):x(_x),y(_y){} 22 | Point operator + (const Point &a) 23 | {return Point(x+a.x,y+a.y);} 24 | Point operator - (const Point &a) 25 | {return Point(x-a.x,y-a.y);} 26 | Point operator * (double rate) 27 | {return Point(x*rate,y*rate);} 28 | double operator * (const Point &a) 29 | {return x*a.x+y*a.y;} 30 | }; 31 | struct GTY 32 | { 33 | Point p; 34 | double g; 35 | friend istream& operator >> (istream &_,GTY &a) 36 | { 37 | scanf("%lf%lf%lf",&a.p.x,&a.p.y,&a.g); 38 | return _; 39 | } 40 | }pt[N]; 41 | double Get_Dis(Point a,Point b) 42 | { 43 | return sqrt((a-b)*(a-b)); 44 | } 45 | Point Get_Direction(Point a) 46 | { 47 | Point p(0,0); 48 | for(int i=1;i<=n;i++) 49 | { 50 | Point tmp=(pt[i].p-a)*(pt[i].g/Get_Dis(pt[i].p,a)); 51 | p=p+tmp; 52 | } 53 | return p; 54 | } 55 | Point Climb_Hill(Point now,double basement) 56 | { 57 | if(basement>pt[i]; 66 | Point Base_Point(1999.5,329.5); 67 | Point ans=Climb_Hill(Base_Point,100000); 68 | cout< 31 | #include 32 | int main(void) { 33 | int num[5][3] = {{5, 6, 4}, 34 | {1, 1, 3}, 35 | {2, 3, 6}, 36 | {3, 2, 9}, 37 | {4, 4, 12}}; 38 | int i, j, k = 1; 39 | printf("sparse matrix:\n"); 40 | for(i = 0; i < 5; i++) { 41 | for(j = 0; j < 3; j++) { 42 | printf("%4d", num[i][j]); 43 | } 44 | putchar('\n'); 45 | } 46 | printf("\nmatrix还原:\n"); 47 | for(i = 0; i < num[0][0]; i++) { 48 | for(j = 0; j < num[0][1]; j++) { 49 | if(k < num[0][2] && 50 | i == num[k][0] && j == num[k][1]) { 51 | printf("%4d ", num[k][2]); 52 | k++; 53 | } 54 | else 55 | printf("%4d ", 0); 56 | } 57 | putchar('\n'); 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /筛选求质数/Eratosthenes.c: -------------------------------------------------------------------------------- 1 | /* 2 | Eratosthenes 3 | 筛选求质数 4 | */ 5 | 6 | #include 7 | #include 8 | #define N 1000 9 | int main(void) { 10 | int i, j; 11 | int prime[N+1]; 12 | for(i = 2; i <= N; i++) 13 | prime[i] = 1; 14 | for(i = 2; i*i <= N; i++) { 15 | if(prime[i] == 1) { 16 | for(j = 2*i; j <= N; j++) { 17 | if(j % i == 0) 18 | prime[j] = 0; 19 | } 20 | } 21 | } 22 | for(i = 2; i < N; i++) { 23 | if(prime[i] == 1) { 24 | printf("%4d ", i); 25 | if(i % 16 == 0) 26 | printf("\n"); 27 | } 28 | } 29 | printf("\n"); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /约束满足搜索/约束满足搜索.c: -------------------------------------------------------------------------------- 1 | 正在更新中... 2 | -------------------------------------------------------------------------------- /线性查找/线性查找.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int linearsearch(int[],int,int); 6 | void BubbleSort(int[],int); 7 | 8 | void main() 9 | { 10 | int n = 100; 11 | a = new int[n]; 12 | 13 | int index,j,temp; 14 | cout<<"Enter number (if you enter 0 , entering will be ended :n"; 15 | cin>>temp; 16 | for(index=0 ; temp != 0 ; index++) 17 | { 18 | a[index] = temp; 19 | cin>>temp; 20 | } 21 | 22 | BubbleSort(a,index); 23 | 24 | cout<<"nTHE SORTED ARRAY IS:n"; 25 | for(i=0 ; i>k; 30 | 31 | int key = linearsearch(a,index,k); 32 | 33 | for(j=key ; ja[j+1]) 49 | { 50 | hold=a[j]; 51 | a[j]=a[j+1]; 52 | a[j+1]=hold; 53 | } 54 | } 55 | 56 | 57 | int linearsearch(int a[],int m,int k) 58 | { 59 | for(int i=0 ; i 4 | int main() 5 | { 6 | int m, n, number=0; 7 | printf(" 红球 白球 黑球\n"); 8 | printf("......................\n"); 9 | for( m=0; m<=3; m++ ) 10 | for( n=0; n<=3; n++ ) 11 | if(8-m-n<=6) 12 | printf(" %2d: %d %d %d\n", ++number, m, n, 8-m-n); 13 | 14 | return 0; 15 | } 16 | 17 | //运行结果: 18 | /* 19 | 红球 白球 黑球 20 | ...................... 21 | 1: 0 2 6 22 | 2: 0 3 5 23 | 3: 1 1 6 24 | 4: 1 2 5 25 | 5: 1 3 4 26 | 6: 2 0 6 27 | 7: 2 1 5 28 | 8: 2 2 4 29 | 9: 2 3 3 30 | 10: 3 0 5 31 | 11: 3 1 4 32 | 12: 3 2 3 33 | 13: 3 3 2 34 | */ 35 | -------------------------------------------------------------------------------- /经典项目/个人所得税问题.c: -------------------------------------------------------------------------------- 1 | //编写一个计算个人所得税的程序,要求输入收入金额后,能够输出应缴的个人所得税。 个人所得税征收办法如下: 2 | //◎ 起征点为3500元; 3 | //◎ 不超过1500元的部分,征收3%; 4 | //◎ 超过1500〜4500元的部分,征收10%; 5 | //◎ 超过4500〜9000元的部分,征收20%; 6 | //◎ 超过9000〜35000元的部分,征收25%; 7 | //◎ 超过35000〜55000元的部分,征收30%; 8 | //◎ 超过55000〜80000元的部分,征收35%; 9 | //◎ 超过80000元以上的,征收45%。 10 | 11 | 12 | #include 13 | #include 14 | #define TAXBASE 2000 15 | /*定义结构体*/ 16 | typedef struct 17 | { 18 | long start; 19 | long end; 20 | double taxrate; 21 | }TAXTABLE; 22 | 23 | TAXTABLE TaxTable[] = { 24 | {0, 1500, 0.03}, 25 | {1500, 4500, 0.10}, 26 | {4500, 9000, 0.20}, 27 | {9000, 35000, 0.25}, 28 | {35000, 55000, 0.30}, 29 | {55000, 80000, 0.35}, 30 | {80000, LONG_MAX, 0.45} 31 | }; 32 | 33 | double CaculateTax(long profit) 34 | { 35 | int i; 36 | double tax = 0.0; 37 | profit -= TAXBASE; 38 | for(i=0; iTaxTable[i].start) 41 | { 42 | if(profit>TaxTable[i].end) 43 | { 44 | tax += (TaxTable[i].end-TaxTable[i].start) * TaxTable[i].taxrate; 45 | } 46 | else 47 | { 48 | tax += (profit-TaxTable[i].start) * TaxTable[i].taxrate; 49 | } 50 | profit -= TaxTable[i].end; 51 | printf("征税范围:%6ld~%6ld 该范围内缴税金额:%6.2f 超出该范围的金额:%6ld\n", 52 | TaxTable[i].start, TaxTable[i].end,tax, (profit)>0 ? profit:0); 53 | } 54 | } 55 | return tax; 56 | } 57 | int main() 58 | { 59 | long profit; 60 | double tax; 61 | printf("请输入个人收入金额: "); 62 | scanf("%ld", &profit); 63 | tax = CaculateTax(profit); 64 | printf("您的个人所得税为: %.2f\n", tax); 65 | 66 | return 0; 67 | } 68 | 69 | 70 | //运行结果: 71 | 72 | //请输入个人收入金额: 100000 73 | //征税范围: 0~ 1500 该范围内缴税金额: 45.00 超出该范围的金额: 96500 74 | //征税范围: 1500~ 4500 该范围内缴税金额:345.00 超出该范围的金额: 92000 75 | //征税范围: 4500~ 9000 该范围内缴税金额:1245.00 超出该范围的金额: 83000 76 | //征税范围: 9000~ 35000 该范围内缴税金额:7745.00 超出该范围的金额: 48000 77 | //征税范围: 35000~ 55000 该范围内缴税金额:11645.00 超出该范围的金额: 0 78 | //您的个人所得税为: 11645.00 79 | -------------------------------------------------------------------------------- /经典项目/借书方案知多少.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/兔子产子问题.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/兔子生兔子的问题.c: -------------------------------------------------------------------------------- 1 | //有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 2 | 3 | //兔子的规律为数列:1, 1, 2, 3, 5, 8, 13, 21 .... 4 | 5 | //下面使用了迭代解法。 6 | 7 | #include 8 | int main() 9 | { 10 | long f1=1, f2=1; // 兔子的数量 11 | int i; // 循环次数 12 | int n; // 要计算的月份 13 | 14 | printf("输入要计算的月数:"); 15 | scanf("%d", &n); 16 | 17 | // 计算出循环次数 18 | if(n%2==1){ 19 | n = (n+1)/2; 20 | }else{ 21 | n = n/2; 22 | } 23 | 24 | for(i=1;i<=n;i++){ 25 | printf("第%d个月有%d只\n", i*2-1, f1); 26 | printf("第%d个月有%d只\n", i*2, f2); 27 | 28 | f1=f1+f2; /*前两个月加起来赋值给第三个月*/ 29 | f2=f1+f2; /*前两个月加起来赋值给第三个月*/ 30 | } 31 | return 0; 32 | } 33 | 34 | 35 | //运行结果: 36 | //运行结果: 37 | //输入要计算的月数:10 38 | //第1个月有1只 39 | //第2个月有1只 40 | //第3个月有2只 41 | //第4个月有3只 42 | //第5个月有5只 43 | //第6个月有8只 44 | //第7个月有13只 45 | //第8个月有21只 46 | //第9个月有34只 47 | //第10个月有55只 48 | // 49 | -------------------------------------------------------------------------------- /经典项目/出售金鱼问题.c: -------------------------------------------------------------------------------- 1 | //小明将养的一缸金鱼分5次出售: 2 | //第1次卖出全部的一半加1/2条; 3 | //第2次卖出余下的三分之一加1/3条; 4 | //第3次卖出余下的四分之一加1/4条; 5 | //第4次卖出余下的五分之一加1/5条; 6 | //最后卖出余下的11条。试编程求出原来鱼缸中共有多少条鱼。 7 | 8 | #include 9 | int main() 10 | { 11 | int i, j, x, flag=0; /*flag作为控制标志*/ 12 | /*从23开始试探,步长为2*/ 13 | for( i=23; flag==0; i+=2 ) 14 | { 15 | for( j=1,x=i; j<=4&&x>=11; j++ ) 16 | if( (x+1) % (j+1) == 0) /*判断x+1是否能整除j+1*/ 17 | x -= (x+1) / (j+1); 18 | else 19 | { 20 | x=0; 21 | break; 22 | } 23 | if(j==5 && x==11) 24 | { 25 | printf("原来鱼缸中共有%d条金鱼。\n", i); 26 | flag = 1; /*求出结果,flag置1,退出试探*/ 27 | } 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | //运行结果: 34 | 35 | //原来鱼缸中共有59条金鱼。 36 | -------------------------------------------------------------------------------- /经典项目/分别用递归法和迭代法求阶乘.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 递归计算阶乘 5 | long factorial_recursion(int n){ 6 | if(n<=0){ 7 | return 1; 8 | }else{ 9 | return n * factorial_recursion(n-1); 10 | } 11 | } 12 | 13 | // 迭代计算阶乘 14 | long factorial_iteration(int n){ 15 | int result = 1; 16 | 17 | while(n>1){ 18 | result *= n; 19 | n--; 20 | } 21 | 22 | return result; 23 | } 24 | 25 | 26 | int main(){ 27 | int N = 10; 28 | long recursion_result = factorial_recursion(N); 29 | long iteration_result = factorial_iteration(N); 30 | 31 | // %ld 输出长整型,即 long int 32 | printf("The factorial(recursion) of %ld is %ld!\n", N, recursion_result); 33 | printf("The factorial(iteration) of %ld is %ld!\n", N, iteration_result); 34 | 35 | return 0; 36 | } 37 | 38 | 39 | //运行结果: 40 | 41 | //The factorial(recursion) of 10 is 3628800! 42 | //The factorial(iteration) of 10 is 3628800! 43 | -------------------------------------------------------------------------------- /经典项目/列出真分数序列.c: -------------------------------------------------------------------------------- 1 | //按递增顺序依次列出所有分母为40,分子小于40的最简分数。 2 | 3 | #include 4 | int main() 5 | { 6 | int i, num1, num2, temp, n=0; /*n记录最简分数的个数*/ 7 | printf("The fraction serials with demominator 40 is:\n"); 8 | for(i=1; i<40; i++) /*穷举40以内的全部分子*/ 9 | { 10 | num1 = 40; 11 | num2 = i; 12 | /*采用辗转相除法求出最大公约数*/ 13 | while(num2 != 0) 14 | { 15 | temp = num1 % num2; 16 | num1 = num2; 17 | num2 = temp; 18 | } 19 | if(num1 == 1) /*若最大公约数为1,则为最简真分数*/ 20 | { 21 | n++; 22 | printf("%2d/40 ", i); 23 | if(n%8 == 0) /*每行输出8个数*/ 24 | printf("\n"); 25 | } 26 | } 27 | 28 | return 0; 29 | } 30 | 31 | //运行结果: 32 | 33 | //The fraction serials with demominator 40 is: 34 | // 1/40 3/40 7/40 9/40 11/40 13/40 17/40 19/40 35 | //21/40 23/40 27/40 29/40 31/40 33/40 37/40 39/40 36 | -------------------------------------------------------------------------------- /经典项目/删除字符数组中特定的字符.c: -------------------------------------------------------------------------------- 1 | //下面的程序将从字符数组中删除特定的字符,要求字符数组和要删除的字符都是手动输入。 2 | //主要涉及知识点:字符数组的输入输出,及相应的处理。 3 | 4 | #include 5 | int main(){ 6 | char s[80], c; 7 | int j, k; 8 | printf("Enter a string: "); 9 | gets(s); 10 | printf("Enter a character: "); 11 | c=getchar( ); 12 | for(j=k=0; s[j]!='\0'; j++) 13 | if(s[j]!=c) 14 | s[k++]=s[j]; 15 | s[k]= '\0'; 16 | printf("\n%s",s); 17 | 18 | return 0; 19 | } 20 | 21 | //运行结果: 22 | //Enter a string: www.0voice.com 23 | //Enter a character:i 24 | //The final string is: www.0voce.com 25 | -------------------------------------------------------------------------------- /经典项目/删除星号.c: -------------------------------------------------------------------------------- 1 | /** 2 | 现在有一串字符需要输入,规定输入的字符串中只包含字母和*号。请编写程序,实现以下功能:除了字符串前后的*号之外,将串中其他的*号全部删除。 3 | 例如,假设输入的字符串为****A*BC*DEF*G********,删除串中的*号后,字符串变为****ABDEFG******** 4 | */ 5 | 6 | #include 7 | int fun(char *a, char *h, char *p) 8 | { 9 | int i, j; 10 | /*删除指针h与p之间的所有“*”*/ 11 | for(i=0,j=0; &h[i] 2 | 3 | int main(){ 4 | int a=0; // 素数的个数 5 | int num=0; // 输入的整数 6 | 7 | printf("输入一个整数:"); 8 | scanf("%d",&num); 9 | 10 | for(int i=2;i 8 | #include 9 | #include 10 | void main(){ 11 | char s[100]; // 存放输入的字符串 12 | int i, j, n; 13 | printf("输入字符串:"); 14 | gets(s); 15 | 16 | n=strlen(s); 17 | for(i=0,j=n-1;i=j) 20 | printf("是回文串\n"); 21 | else 22 | printf("不是回文串\n"); 23 | } 24 | 25 | //运行结果: 26 | 27 | //输入字符串:abcdcba 28 | //是回文串 29 | -------------------------------------------------------------------------------- /经典项目/动态分配数组大小.c: -------------------------------------------------------------------------------- 1 | //我们知道,C语言中的数组大小是固定的,定义的时候必须要给一个常量值,不能是变量。 2 | 3 | //这带来了很大的不便,如果数组过小,不能容下所有数组,如果过大,浪费资源。 4 | 5 | //下面的代码实现了简单的动态数组: 6 | 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | //从控制台获取初始数组大小 13 | int N; 14 | int *a; 15 | int i; 16 | 17 | printf("Input array length:"); 18 | scanf("%d\n",&N); 19 | 20 | //分配空间 21 | a=(int *)calloc(N,sizeof(int)); 22 | //填充数据 23 | for(i=0;i 9 | #include 10 | #include 11 | 12 | #define FILE_PATH "D:/demo.txt" // 文件路径 13 | 14 | int main(){ 15 | char name[20]; // 姓名 16 | int age; // 年龄 17 | int studNo; // 学号 18 | float score; // 平均分 19 | FILE *fp; // 文件指针 20 | 21 | // 判断文件是否能够正确创建/打开 22 | if( (fp=fopen(FILE_PATH,"wt+")) == NULL ){ 23 | perror(FILE_PATH); 24 | exit(1); 25 | } 26 | 27 | // 从控制台输入学生信息并写入文件 28 | printf("请输入姓名、年龄、学号和平均分(以空格分隔):\n"); 29 | while(scanf("%s %d %d %f", name, &age, &studNo, &score)!= EOF){ 30 | fprintf(fp,"%s\t%d\t%d\t%f\n", name, age, studNo, score); 31 | } 32 | // 刷新缓冲区,将缓冲区的内容写入文件 33 | fflush(fp); 34 | // 重置文件内部位置指针,让位置指针指向文件开头 35 | rewind(fp); 36 | 37 | // 从文件中读取学生信息 38 | printf("\n读取文件内容:\n"); 39 | while(fscanf(fp, "%s\t%d\t%d\t%f", name, &age, &studNo, &score) != EOF){ 40 | printf("%s %d %d %f\n", name, age, studNo, score); 41 | } 42 | fclose(fp); 43 | 44 | return EXIT_SUCCESS; 45 | } 46 | 47 | 48 | //运行结果: 49 | 50 | //请输入姓名、年龄、学号和平均分(以空格分隔): 51 | //棍哥 25 1 99.99 52 | //码农宿舍 2 3 89.9 53 | //www.0voice.com 3 2 100 54 | //^Z // ^Z 为 Ctrl+Z 组合键,表示输入结束 55 | 56 | //读取文件内容: 57 | //棍哥 25 1 99.989998 58 | //码农宿舍 2 3 89.900002 59 | //www.0voice.com 3 2 100.000000 60 | -------------------------------------------------------------------------------- /经典项目/在字符串的指定位置插入字符.c: -------------------------------------------------------------------------------- 1 | /** 2 | 请编写程序,实现以下功能:在字符串中的所有数字字符前加一个$字符。例如,输入 A1B23CD45,输出 A$1B$2$3CD$4$5。 3 | */ 4 | 5 | #include 6 | int fun(char *s) 7 | { 8 | char t[80]; 9 | int i, j; 10 | for(i=0; s[i]; i++) /*将串s拷贝至串t*/ 11 | t[i]=s[i]; 12 | t[i]='\0'; 13 | for(i=0,j=0; t[i]; i++) 14 | /*对于数字字符先写一个$符号,再写该数字字符*/ 15 | if(t[i]>='0' && t[i]<='9') 16 | { 17 | s[j++]='$'; 18 | s[j++]=t[i]; 19 | } 20 | /*对于非数字字符原样写入串s*/ 21 | else 22 | s[j++]=t[i]; 23 | s[j]='\0'; /*在串s结尾加结束标志*/ 24 | return 0; 25 | } 26 | int main() 27 | { 28 | char s[80]; 29 | printf ( "Enter a string:" ); 30 | scanf ("%s", s); /*输入字符串*/ 31 | fun(s); 32 | printf ("The result: %s\n", s); /*输出结果*/ 33 | return 0; 34 | } 35 | 36 | //运行结果: 37 | 38 | //Enter a string:A1B23CD45 39 | //The result: A$1B$2$3CD$4$5 40 | -------------------------------------------------------------------------------- /经典项目/奶牛生子的问题.c: -------------------------------------------------------------------------------- 1 | //一只刚出生的奶牛,4年生1只奶牛,以后每一年生1只。现在给你一只刚出生的奶牛,求20年后有多少奶牛。 2 | 3 | //本题主要考察读者的分析能力,已知条件有两: 4 | //第一次,4年生一只。 5 | //然后每年生一只。 6 | 7 | //需要的结果中也提供了一个条件,就是20年。读者要注意的本题最难的地方是不光这只奶牛会生奶牛,它的孩子的孩子也会继续生奶牛,读者通过分析下面的代码就能看到难点所在。 8 | 9 | #include 10 | 11 | int CalCowsNum(int iYear){ 12 | int iCnt =0; 13 | long lCowsNum = 1; //奶牛总数 14 | for(iCnt=1; iCnt<=iYear; iCnt++){ 15 | if(iCnt>=4){ //4年以后奶牛数量开始增多 16 | if((iYear-iCnt)>3){ //第2个4年开始后产的奶牛开始生新奶牛 17 | lCowsNum += CalCowsNum(iYear - iCnt); 18 | }else{ 19 | lCowsNum++; 20 | } 21 | } 22 | } 23 | 24 | return lCowsNum; //返回奶牛总数 25 | } 26 | 27 | int main(){ 28 | int iYear =0; 29 | printf("Please input require years:"); 30 | scanf ("%d", &iYear); //输入年数 31 | printf("In %d years, There is %d cows.\n", iYear, CalCowsNum(iYear)); //输出结果 32 | 33 | return 0; 34 | } 35 | 36 | 37 | //运行结果: 38 | //Please input require years:20 39 | //In 20 years, There is 345 cows. 40 | -------------------------------------------------------------------------------- /经典项目/委派任务问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | 某项任务需要在A、B、C、D、E、F这6个人中挑选人来完成,但挑选人受限于以下的条件: 3 | (1) A和B两个人至少去一人; 4 | (2) A和D不能同时去; 5 | (3) A、E和F三人中要挑选两个人去; 6 | (4) B和C同时去或者都不去; 7 | (5) C和D两人中只能去一个; 8 | (6) 如果D不去,那么E也不去。 9 | 10 | 试编程求出应该让哪几个人去完成这项任务。 11 | */ 12 | 13 | #include 14 | 15 | int main() 16 | { 17 | int A, B, C, D, E, F; 18 | for(A=0; A<=1; A++) 19 | for(B=0; B<=1; B++) 20 | for(C=0; C<=1; C++) 21 | for(D=0; D<=1; D++) 22 | for(E=0; E<=1; E++) 23 | for(F=0; F<=1; F++) 24 | if(A+B>=1 && A+D!=2 && A+E+F==2 25 | && (B+C==0 || B+C==2) 26 | && C+D==1 && (D+E==0 || D==1)) 27 | { 28 | printf("A%s被选择去完成任务。\n",A?"":"未"); 29 | printf("B%s被选择去完成任务。\n",B?"":"未"); 30 | printf("C%s被选择去完成任务。\n",C?"":"未"); 31 | printf("D%s被选择去完成任务。\n",D?"":"未"); 32 | printf("E%s被选择去完成任务。\n",E?"":"未"); 33 | printf("F%s被选择去完成任务。\n",F?"":"未"); 34 | 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | //运行结果: 41 | 42 | //A被选择去完成任务。 43 | //B被选择去完成任务。 44 | //C被选择去完成任务。 45 | //D未被选择去完成任务。 46 | //E未被选择去完成任务。 47 | //F被选择去完成任务。 48 | -------------------------------------------------------------------------------- /经典项目/存钱问题.c: -------------------------------------------------------------------------------- 1 | //假设银行整存整取存款不同期限的月息利率为: 2 | 3 | //0.63% 期限为1年 4 | //0.66% 期限为2年 5 | //0.69% 期限为3年 6 | //0.75% 期限为5年 7 | //84% 期限为8年 8 | 9 | //现在已知某人手上有2000元,要求通过计算选择出一种存钱方案,使得这笔钱存入银行20年后获得的利息最多,假定银行对超出存款期限的那部分时间不付利息。 10 | 11 | #include 12 | #include 13 | 14 | int main() 15 | { 16 | int x1, x2, x3, x5, x8; 17 | int y1 = 0, y2 = 0, y3 = 0, y5 = 0, y8 = 0; 18 | double max=0.0, result = 0.0; /*result变量存放最后结果*/ 19 | /*使用for循环穷举所有可能存款方案*/ 20 | for( x8=0; x8<=2; x8++ ) 21 | for( x5=0; x5<=(20-8*x8)/5; x5++ ) 22 | for( x3=0; x3<=(20-8*x8-5*x5)/3; x3++ ) 23 | for( x2=0; x2<=(20-8*x8-5*x5-3*x3)/2; x2++ ) 24 | { 25 | x1 = 20 - 8*x8 - 5*x5 - 3*x3 - 2*x2; /*存款期限限定条件*/ 26 | /*判断条件*/ 27 | result = 2000.0 * pow( (1+0.0063*12), x1) 28 | *pow( (1+2*0.0066*12), x2) 29 | *pow( (1+3*0.0069*12), x3) 30 | *pow( (1+5*0.0075*12), x5) 31 | *pow( (1+8*0.0084*12), x8); 32 | /*y1,y2,y3,y5,y8用于记录获利最多的存放方式*/ 33 | if(result>max) 34 | { 35 | max = result; /*max变量存放当前的最大值*/ 36 | y1 = x1; 37 | y2 = x2; 38 | y3 = x3; 39 | y5 = x5; 40 | y8 = x8; 41 | } 42 | } 43 | 44 | /*输出结果*/ 45 | printf("获得利息最多的存款方式为:\n"); 46 | printf("8年期限的存了%d次\n", y8); 47 | printf("5年期限的存了%d次\n", y5); 48 | printf("3年期限的存了%d次\n", y3); 49 | printf("2年期限的存了%d次\n", y2); 50 | printf("1年期限的存了%d次\n", y1); 51 | printf("存款人最终的获得的本利合计:%0.2f\n", result); 52 | 53 | return 0; 54 | } 55 | 56 | 57 | //运行结果: 58 | 59 | //获得利息最多的存款方式为: 60 | //8年期限的存了0次 61 | //5年期限的存了4次 62 | //3年期限的存了0次 63 | //2年期限的存了0次 64 | //1年期限的存了0次 65 | //存款人最终的获得的本利合计:8763.19 66 | -------------------------------------------------------------------------------- /经典项目/定时关机小程序.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void main() 6 | { 7 | char cmd[20]="shutdown -s -t "; 8 | char t[5]="0"; 9 | int c; 10 | 11 | system("title C语言关机程序"); //设置cmd窗口标题 12 | system("mode con cols=48 lines=25"); //窗口宽度高度 13 | system("color f0"); //可以写成 red 调出颜色组 14 | system("date /T"); 15 | system("TIME /T"); 16 | 17 | printf("----------- C语言关机程序 -----------\n"); 18 | printf("1.实现10分钟内的定时关闭计算机\n"); 19 | printf("2.立即关闭计算机\n"); 20 | printf("3.注销计算机\n"); 21 | printf("0.退出系统\n"); 22 | printf("-------------------------------------\n"); 23 | 24 | scanf("%d",&c); 25 | switch(c) { 26 | case 1: 27 | printf("您想在多少秒后自动关闭计算机?(0~600)\n"); 28 | scanf("%s",t); 29 | system(strcat(cmd,t)); 30 | break; 31 | case 2: 32 | system("shutdown -p"); 33 | break; 34 | case 3: 35 | system("shutdown -l"); 36 | break; 37 | case 0: 38 | break; 39 | default: 40 | printf("Error!\n"); 41 | } 42 | system("pause"); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /经典项目/定时关机程序.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/实现动态数组,克服静态数组大小固定的缺陷.c: -------------------------------------------------------------------------------- 1 | //C语言中,数组长度必须在创建数组时指定,并且只能是一个常数,不能是变量。一旦定义了一个数组,系统将为它分配一个固定大小的空间,以后不能改变,称为静态数组。但在编程过程中,有时我们所需的内存空间无法预先确定,对于这个问题,用静态数组的办法很难解决。 2 | 3 | //动态数组是相对于静态数组而言。静态数组的长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程序需要而重新指定大小。动态数组的内存空间是从堆(heap)上分配(即动态分配)的。是通过执行代码而为其分配存储空间。当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。 4 | 5 | //那么,如何创建动态数组,按照需要设置数组大小呢? 6 | 7 | 8 | #include 9 | #include 10 | 11 | int main(){ 12 | int arrLen; // 数组长度 13 | int *array; // 数组指针 14 | int i; // 数组下标 15 | 16 | printf("输入数组长度:"); 17 | scanf("%d", &arrLen); 18 | 19 | // 动态分配内存空间,如果失败就退出程序 20 | array = (int*)malloc( arrLen*sizeof(int) ); 21 | if(!array){ 22 | printf("创建数组失败!\n"); 23 | exit(1); 24 | } 25 | // 向内存中写入数据 26 | for(i=0; i 5 | #include 6 | #include 7 | 8 | // argc: 统计运行程序时命令行参数的个数 9 | // *argv[]: 储存每个参数的字符串指针,每一个元素对应一个参数 10 | int main (int argc,char *argv[]) 11 | { 12 | int ch,bian=0,count=0; 13 | char find[50],temp[1000]; 14 | FILE *pt; //文件指针 15 | 16 | // 判断是否输入文件 17 | if (argc != 2){ 18 | printf("请使用格式: %s 文件名",argv[0]); 19 | exit(1); //非正常退出 20 | } 21 | 22 | // 判断能否成功打开文件 23 | if ((pt = fopen(argv[1],"r"))== NULL){ //将argv[1]赋值给指针pt 24 | printf("打开文件 %s 失败",argv[1]); 25 | exit(1); 26 | } 27 | 28 | printf("请输入要查找的单词:"); 29 | gets(find); 30 | while((ch=getc(pt))!=EOF){ //EOF 表示文件结束 31 | if ((ch!=' ')&&(ch!='\n')){ 32 | temp[bian]=ch; 33 | bian++; 34 | } else { 35 | temp[bian]='\0'; 36 | if ((strcmp(find,temp))==0) count++; 37 | bian=0; 38 | } 39 | } 40 | printf("共在文件%s中查找到字符串\"%s\" %d 个\n",argv[1],find,count); 41 | 42 | getch(); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /经典项目/实现的猜拳游戏(剪子锤子布).c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/将一个正整数分解质因数.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | int n; // 用户输入的整数 5 | int i; // 循环标志 6 | 7 | printf("输入一个整数:"); 8 | scanf("%d",&n); 9 | printf("%d=",n); 10 | 11 | // n>=2才执行下面的循环 12 | for(i=2; i<=n; i++){ 13 | while(n!=i){ 14 | if(n%i==0){ 15 | printf("%d*",i); 16 | n=n/i; 17 | }else 18 | break; 19 | } 20 | } 21 | printf("%d\n",n); 22 | 23 | return 0; 24 | } 25 | 26 | 27 | //运行结果: 28 | 29 | //输入一个整数:10000 30 | //10000=2*2*2*2*5*5*5*5 31 | -------------------------------------------------------------------------------- /经典项目/将字符串转换为整数.c: -------------------------------------------------------------------------------- 1 | //自定义一个函数,将字符串转换为整数,原型为: 2 | // 3 | //int ascii_to_integer( char *string ); 4 | // 5 | //这个字符串参数必须包含一个或多个数字,函数应该把这些数字字符转换为整数并返回这个整数。如果字符串参数包含了任何非数字字符,函数就返回零。请不必担心算术溢出。 6 | //提示:这个技巧很简单你每发现一个数字,把当前值乘以10,并把这个值和新数字所代表的值相加。 7 | //这个问题应该用迭代方法解决,而不应采用递归方法。 8 | 9 | 10 | #include 11 | 12 | // 把一个数字字符串转换为一个整数。 13 | int ascii_to_integer( char *string ) 14 | { 15 | int value; value = 0; 16 | 17 | // 逐个把字符串的字符转换为数字。 18 | while( *string >= '0' && *string <= '9' ){ 19 | value *= 10; 20 | value += *string - '0'; 21 | string++; 22 | } 23 | 24 | //错误检查:如杲由于遇到一个非数字字符而终止,把结果设置为0 25 | if( *string != '\0' ) 26 | value = 0; 27 | return value; 28 | } 29 | 30 | int main() 31 | { 32 | char* numChar = "102"; 33 | printf("%d\n", ascii_to_integer(numChar)+3); 34 | 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /经典项目/将真分数分解为埃及分数.c: -------------------------------------------------------------------------------- 1 | //现输入一个真分数,请将该分数分解为埃及分数。 2 | 3 | #include 4 | int main() 5 | { 6 | long int a, b, c; 7 | printf("Please enter a optional fraction(a/b):"); 8 | scanf("%ld/%ld", &a, &b); /*输入分子a和分母b*/ 9 | printf("It can be decomposed to:"); 10 | while(1) 11 | { 12 | if(b%a) /*若分子不能整除分母,则分解出一个分母为b/a+1的埃及分数*/ 13 | c = b/a + 1; 14 | else /*否则,输出化简后的真分数(埃及分数)*/ 15 | { 16 | c = b / a; 17 | a = 1; 18 | } 19 | if(a==1) 20 | { 21 | printf("1/%ld\n", c); 22 | break; /*a为1标志结束*/ 23 | } 24 | else 25 | printf("1/%ld + ", c); 26 | a = a * c - b; /*求出余数的分子*/ 27 | b = b * c; /*求出余数的分母*/ 28 | if(a==3 && b%2==0) /*若余数分子为3,分母为偶数,输出最后两个埃及分数*/ 29 | { 30 | printf("1/%ld + 1/%ld\n", b/2, b); 31 | break; 32 | } 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | //运行结果: 39 | 40 | //Please enter a optional fraction(a/b):8/11 41 | //It can be decomposed to:1/2 + 1/5 + 1/55 + 1/110 42 | -------------------------------------------------------------------------------- /经典项目/常胜将军问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | 有21根火柴,两人依次取,每次每人只可取走1〜4根,不能多取,也不能不取,谁取到最后一根火柴谁输。 3 | 请编写一个人机对弈程序,要求人先取,计算机后取;计算机为“常胜将军”。 4 | */ 5 | 6 | #include 7 | int main() 8 | { 9 | int computer, people, spare = 21; 10 | printf(" -----------------------------------------\n"); 11 | printf(" -------- 你不能战胜我,不信试试 --------\n"); 12 | printf(" -----------------------------------------\n\n"); 13 | printf("Game begin:\n\n"); 14 | while(1) 15 | { 16 | printf(" ---------- 目前还有火柴 %d 根 ----------\n", spare); 17 | printf("People:"); 18 | scanf("%d", &people); 19 | if(people<1 || people>4 || people>spare) 20 | { 21 | printf("你违规了,你取的火柴数有问题!\n\n"); 22 | continue; 23 | } 24 | spare = spare - people; 25 | if( spare==0 ) 26 | { 27 | printf("\nComputer win! Game Over!\n"); 28 | break; 29 | } 30 | computer = 5 - people; 31 | spare = spare - computer; 32 | printf("Computer:%d \n", computer); 33 | if( spare==0 ) 34 | { 35 | printf("\nPeople win! Game Over!\n"); 36 | break; 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | //运行结果: 43 | 44 | /** 45 | ----------------------------------------- 46 | -------- 你不能战胜我,不信试试 -------- 47 | ----------------------------------------- 48 | 49 | Game begin: 50 | 51 | ---------- 目前还有火柴 21 根 ---------- 52 | People:1 53 | Computer:4 54 | ---------- 目前还有火柴 16 根 ---------- 55 | People:3 56 | Computer:2 57 | ---------- 目前还有火柴 11 根 ---------- 58 | People:2 59 | Computer:3 60 | ---------- 目前还有火柴 6 根 ---------- 61 | People:4 62 | Computer:1 63 | ---------- 目前还有火柴 1 根 ---------- 64 | People:1 65 | 66 | Computer win! Game Over! 67 | */ 68 | -------------------------------------------------------------------------------- /经典项目/平分7筐鱼.c: -------------------------------------------------------------------------------- 1 | /** 2 | 甲、乙、丙三位渔夫出海打鱼,他们随船带了21只箩筐。当晚返航时,他们发现有7筐装满了鱼,还有7筐装了半筐鱼, 3 | 另外7筐则是空的,由于他们没有秤,只好通过目测认为7个满筐鱼的重量是相等的,7个半筐鱼的重量是相等的。在不 4 | 将鱼倒出来的前提下,怎样将鱼平分为3份? 5 | */ 6 | 7 | #include 8 | int a[3][3], count; 9 | int main() 10 | { 11 | int i, j, k, m, n, flag; 12 | printf("It exists possible distribtion plans:\n"); 13 | for(i=0; i<=3; i++) /*试探第一个人满筐a[0][0]的值,满筐数不能>3*/ 14 | { 15 | a[0][0]=i; 16 | for(j=i; j<=7-i&&j<=3; j++) /*试探第二个人满筐a[1][0]的值,满筐数不能>3*/ 17 | { 18 | a[1][0]=j; 19 | if((a[2][0]=7-j-a[0][0])>3) 20 | continue; /*第三个人满筐数不能>3*/ 21 | if(a[2][0] 7 | #define N 14 8 | void main() 9 | { 10 | int i, j, k, n=0, a[N][N]; /*定义二维数组a[14][14]*/ 11 | while(n<=0||n>=13){ /*控制打印的行数不要太大,过大会造成显示不规范*/ 12 | printf("请输入要打印的行数:"); 13 | scanf("%d",&n); 14 | } 15 | printf("%d行杨辉三角如下:\n",n); 16 | for(i=1;i<=n;i++) 17 | a[i][1] = a[i][i] = 1; /*两边的数令它为1,因为现在循环从1开始,就认为a[i][1]为第一个数*/ 18 | for(i=3;i<=n;i++) 19 | for(j=2;j<=i-1;j++) 20 | a[i][j]=a[i-1][j-1]+a[i-1][j]; /*除两边的数外都等于上两顶数之和*/ 21 | for(i=1;i<=n;i++){ 22 | for(k=1;k<=n-i;k++) 23 | printf(" "); /*这一行主要是在输出数之前打上空格占位,让输出的数更美观*/ 24 | for(j=1;j<=i;j++) /*j<=i的原因是不输出其它的数,只输出我们想要的数*/ 25 | printf("%6d",a[i][j]); 26 | 27 | printf("\n"); /*当一行输出完以后换行继续下一行的输出*/ 28 | } 29 | printf("\n"); 30 | } 31 | 32 | 33 | //运行结果: 34 | //请输入要打印的行数:10 35 | //10行杨辉三角如下: 36 | // 1 37 | // 1 1 38 | // 1 2 1 39 | // 1 3 3 1 40 | // 1 4 6 4 1 41 | // 1 5 10 10 5 1 42 | // 1 6 15 20 15 6 1 43 | // 1 7 21 35 35 21 7 1 44 | // 1 8 28 56 70 56 28 8 1 45 | // 1 9 36 84 126 126 84 36 9 1 46 | -------------------------------------------------------------------------------- /经典项目/打鱼还是晒网问题.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/找到一个数的所有真因子.c: -------------------------------------------------------------------------------- 1 | //下面的代码,提示用户输入一个整数,并判断是否是素数,如果是将输出它本身,否则输出所有的真因子。 2 | 3 | 4 | #include 5 | 6 | int main(void) { 7 | int n, 8 | lcv, 9 | flag; // flag 被初始化为 1,如果后续判断 n 不是素数,那么它将变为 0 10 | 11 | printf("Enter value of N > "); 12 | scanf("%d", &n); 13 | for (lcv=2, flag=1; lcv <= (n / 2); lcv++) { 14 | if ((n % lcv) == 0) { 15 | if (flag) 16 | printf("The non-trivial factors of %d are: \n", n); 17 | flag = 0; 18 | printf("\t%d\n", lcv); 19 | } 20 | } 21 | if (flag) 22 | printf("%d is prime\n", n); 23 | } 24 | 25 | 26 | //可能的输出结果: 27 | //Enter value of N > 100 The non-trivial factors of 100 are: 28 | // 2 29 | // 4 30 | // 5 31 | // 10 32 | // 20 33 | // 25 34 | // 50 35 | -------------------------------------------------------------------------------- /经典项目/抓交通肇事犯问题.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/换分币问题.c: -------------------------------------------------------------------------------- 1 | //将5元的人民币兑换成1元、5角和1角的硬币,共有多少种不同的兑换方法。 2 | 3 | #include 4 | int main() 5 | { 6 | int x, y, z, count=1; 7 | printf("可能的兑换方法如下:\n"); 8 | for( x=0; x<=50; x+=10 ) /*x为1元硬币钱数,其取值为0,10,20,30,40,50*/ 9 | for( y=0; y<=50-x; y+=5 ) /*y为5角硬币钱数,其取值为0,5,10,15,20,25,30,35,40,,45,50*/ 10 | for( z=0; z<=50-x-y; z++) /*z为1角硬币钱数,其取值为0,1,...50*/ 11 | if(x+y+z==50) 12 | { 13 | /*输出时,每行最多三种情况*/ 14 | printf(count%3 ? "%d: 10*%d+5*%d+1*%d\t" : "%d:10*%d+5*%d+1*%d\n", count, x/10, y/5, z); 15 | count++; 16 | } 17 | return 0; 18 | } 19 | 20 | //运行结果: 21 | 22 | //可能的兑换方法如下: 23 | //1: 10*0+5*0+1*50 2: 10*0+5*1+1*45 3:10*0+5*2+1*40 24 | //4: 10*0+5*3+1*35 5: 10*0+5*4+1*30 6:10*0+5*5+1*25 25 | //7: 10*0+5*6+1*20 8: 10*0+5*7+1*15 9:10*0+5*8+1*10 26 | //10: 10*0+5*9+1*5 11: 10*0+5*10+1*0 12:10*1+5*0+1*40 27 | //13: 10*1+5*1+1*35 14: 10*1+5*2+1*30 15:10*1+5*3+1*25 28 | //16: 10*1+5*4+1*20 17: 10*1+5*5+1*15 18:10*1+5*6+1*10 29 | //19: 10*1+5*7+1*5 20: 10*1+5*8+1*0 21:10*2+5*0+1*30 30 | //22: 10*2+5*1+1*25 23: 10*2+5*2+1*20 24:10*2+5*3+1*15 31 | //25: 10*2+5*4+1*10 26: 10*2+5*5+1*5 27:10*2+5*6+1*0 32 | //28: 10*3+5*0+1*20 29: 10*3+5*1+1*15 30:10*3+5*2+1*10 33 | //31: 10*3+5*3+1*5 32: 10*3+5*4+1*0 33:10*4+5*0+1*10 34 | //34: 10*4+5*1+1*5 35: 10*4+5*2+1*0 36:10*5+5*0+1*0 35 | -------------------------------------------------------------------------------- /经典项目/掷骰子游戏.c: -------------------------------------------------------------------------------- 1 | /** 2 | 骰子是一个有六个面的正方体,每个面分别印有1〜6之间的小圆点代表点数。假设这个游戏的规则是: 3 | 两个人轮流掷骰子6次,并将每次投掷的点数累加起来。点数多者获胜;点数相同则为平局。 4 | 5 | 要求编写程序模拟这个游戏的过程,并求出玩100盘之后谁是最终的获胜者。 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | int main() 12 | { 13 | int d1, d2, c1, c2, i, j; 14 | c1 = c2 = 0; /*初始化*/ 15 | srand((unsigned)time(NULL)); 16 | rand(); /*初始化随机数产生器*/ 17 | for(i=1; i<=100; i++) 18 | { /*模拟游戏过程*/ 19 | d1 = d2 = 0; 20 | for(j=1; j<=6; j++) 21 | { /*两个人轮流掷骰子*/ 22 | d1 = d1+rand()+1; 23 | d2 = d2+rand()+1; 24 | } 25 | if(d1>d2) 26 | c1++; /*累加获胜盘数*/ 27 | else if(d1c2) /*输出最终获胜者信息*/ 31 | printf("\nThe first win.\n"); 32 | else 33 | if (c1 7 | int main(){ 8 | int a[4][4],b[4][4],i,j; /*a 存放原始数组数据,b 存放旋转后数组数据*/ 9 | printf("input 16 numbers: "); 10 | /*输入一组数据存放到数组 a 中,然后旋转存放到 b 数组中*/ 11 | for(i=0;i<4;i++){ 12 | for(j=0;j<4;j++){ 13 | scanf("%d",&a[i][j]); 14 | printf("%6d",a[i][j]); 15 | b[3-j][i]=a[i][j]; 16 | } 17 | printf("\n"); 18 | } 19 | printf("array b:\n"); 20 | for(i=0;i<4;i++){ 21 | for(j=0;j<4;j++) 22 | printf("%6d",b[i][j]); 23 | printf("\n"); 24 | } 25 | return 0; 26 | } 27 | 28 | //运行结果: 29 | //input 16 numbers: 1 34 6 4 56 2 5 6 9 12 23 23 46 77 12 34 30 | // 1 34 6 4 31 | // 56 2 5 6 32 | // 9 12 23 23 33 | // 46 77 12 34 34 | //array b: 35 | // 4 6 23 34 36 | // 6 5 23 12 37 | // 34 2 12 77 38 | // 1 56 9 46 39 | -------------------------------------------------------------------------------- /经典项目/文本文件复制代码.c: -------------------------------------------------------------------------------- 1 | //下面的程序,与 Unix 的 cp 命令类似,需要两个文件名作为参数,将第一个文件的内容复制到第二个文件。 2 | 3 | //该程序涉及到main()函数传参的问题,请查看:C语言mian()函数详解 4 | 5 | 6 | #include 7 | #include 8 | 9 | int main(int argc, char * argv[]){ 10 | FILE *fin, *fout; 11 | char c; 12 | 13 | if (argc!=3){ 14 | printf("Usage: %s filein fileout\n", argv[0]); 15 | exit(0); 16 | } 17 | if ((fin=fopen(argv[1],"r"))==NULL){ 18 | perror("fopen filein"); 19 | exit(0); 20 | } 21 | if ((fout=fopen(argv[2],"w"))==NULL){ 22 | perror("fopen fileout"); 23 | exit(0); 24 | } 25 | 26 | while ((c=getc(fin))!=EOF) 27 | putc(c,fout); 28 | 29 | fclose(fin); 30 | fclose(fout); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /经典项目/新娘和新郎问题.c: -------------------------------------------------------------------------------- 1 | //对情侣参加婚礼,3个新郞为A、B、C,3个新娘为X、Y、Z,有人不知道谁和谁结婚,于是询问了6位新人中的3位,但听到的回答是这样的:A说他将和X结婚;X说她的未婚夫是C; C说他将和Z结婚。这人听后知道他们在开玩笑,全是假话。请编程找出谁将和谁结婚。 2 | //算法分析 3 | //将A、B、C这3人用 1、2、3 表示,将X和A结婚表示为“X=1”,将Y不与A结婚表示为“Y!=1”。按照题目中的叙述可以写出表达式: 4 | //x!=1 A不与X结婚 5 | //x!=3 X的未婚夫不是C 6 | //z!=3 C不与Z结婚题意还隐含着X、Y、Z这3个新娘不能结为配偶,则有:x!=y 且x!=z且y!=z,穷举以上所有可能的情况,代入上述表达式中进行推理运算,若假设的情况使上述表达式的结果均为真,则假设情况就是正确的结果。 7 | 8 | //根据算法分析,可以利用计算机程序对这些情况进行穷举,然后得出正确的结果。 9 | //根据算法分析,该问题的程序实现如下: 10 | 11 | 12 | #include 13 | 14 | void Marry(void); 15 | 16 | int main(){ 17 | Marry(); 18 | 19 | return 0; 20 | } 21 | 22 | void Marry(){ 23 | int x, y, z; 24 | for (x=1;x<=3;x++) //穷举x的全部可能配偶 25 | for (y=1;y<=3;y++) //穷举y的全部可能配偶 26 | for(z=1;z<=3;z++) //穷举z的全部可能配偶 27 | if (x!=1 && x!=3 && z!=3 && x!=y && x!=z && y!=z){ //判断配偶是否满足题意 28 | printf ("X和%c结婚\n", 'A'+x-1); //打印判断结果 29 | printf ("Y和%c结婚\n", 'A'+y-1); 30 | printf ("Z和%c结婚\n", 'A'+z-1); 31 | } 32 | } 33 | 34 | 35 | //运行结果: 36 | //X和B结婚 37 | //Y和C结婚 38 | //Z和A结婚 39 | -------------------------------------------------------------------------------- /经典项目/新郎和新娘问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | 有3对情侣结婚,假设2个新郎为A、B、C,3个新娘为X、Y、Z,有参加婚礼的人搞不清谁和谁结婚,所以去询问了这6位新人中的3位, 3 | 得到的回答如下:新郎A说他要和新娘X结婚;新娘X说她的未婚夫是新郎C;而新郎C说他要和新娘Z结婚。 4 | 5 | 听到这样的回答后,提问者知道他们都是在开玩笑,说的都是假话,但他仍搞不清谁和谁结婚,现在请编程求出到底哪位新郎和哪位新 6 | 娘结婚。 7 | */ 8 | 9 | #include 10 | int main() 11 | { 12 | char x, y, z; 13 | for(x='A'; x<='C'; x++) 14 | for(y='A'; y<='C'; y++) 15 | for(z='A'; z<='C'; z++) 16 | if(x!='A' && x!='C' && z!='C' && x!=y && x!=z && y!=z) 17 | { 18 | printf("结果为:\n"); 19 | printf("新娘X与新郎%c结婚。\n", x); 20 | printf("新娘Y与新郎%c结婚。\n", y); 21 | printf("新娘Z与新郎%c结婚。\n", z); 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | //运行结果: 28 | 29 | //结果为: 30 | //新娘X与新郎B结婚。 31 | //新娘Y与新郎C结婚。 32 | //新娘Z与新郎A结婚。 33 | -------------------------------------------------------------------------------- /经典项目/最佳存款方案.c: -------------------------------------------------------------------------------- 1 | //假设银行一年整存零取的月息为 0.63%。现在某人手中有一笔钱,他打算在今后的 5 年中的每年年底取出 1000 元,到第 5 年时刚好取完,请算出他存钱时应存入多少。 2 | 3 | 4 | #include 5 | int main() 6 | { 7 | int i; 8 | double money=0.0; 9 | for(i=0; i<5; i++) 10 | money=(money+1000.0)/(1+0.0063*12); 11 | printf("应存入的钱数为:%0.2f\n", money); /*结果保留两位小数*/ 12 | return 0; 13 | } 14 | 15 | //运行结果: 16 | 17 | //应存入的钱数为:4039.44 18 | -------------------------------------------------------------------------------- /经典项目/歌星大奖赛.c: -------------------------------------------------------------------------------- 1 | //在歌星大奖赛中,有10个评委为参赛的选手打分,分数为1〜100分。选手最后得分为:去掉一个最高分和一个最低分后其余8个分数的平均值。请编写一个程序实现。 2 | 3 | #include 4 | int main() 5 | { 6 | int m, n, temp, i; 7 | printf("Input m & n:"); 8 | scanf("%d%d", &m, &n); 9 | if(m0; i++) /*从大数开始寻找满足条件的自然数*/ 16 | if(i%m==0 && i%n==0) 17 | {/*输出满足条件的自然数并结束循环*/ 18 | printf("The LCW of %d and %d is: %d\n", m, n, i); 19 | break; 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | //运行结果: 26 | 27 | //Input m & n:6 24 28 | //The LCW of 24 and 6 is: 24 29 | -------------------------------------------------------------------------------- /经典项目/比较两个分数的大小.c: -------------------------------------------------------------------------------- 1 | //比较两个分数的大小。 2 | 3 | #include 4 | int zxgb(int a, int b); /*函数声明*/ 5 | int main() 6 | { 7 | int i, j, k, l, m, n; 8 | printf("Input two FENSHU:\n"); 9 | scanf("%d/%d,%d/%d", &i, &j, &k, &l); /*输入两个分数*/ 10 | m=zxgb(j, l)/j*i; /*求出第一个分数通分后的分子*/ 11 | n=zxgb(j, l)/l*k; /*求出第二个分数通分后的分子*/ 12 | if(m>n) /*比较分子的大小*/ 13 | printf("%d/%d>%d/%d\n", i, j, k, l); 14 | else 15 | if(m == n) 16 | printf("%d/%d=%d/%d\n", i, j, k, l); /*输出比较的结果*/ 17 | else 18 | printf("%d/%d<%d/%d\n", i, j, k, l); 19 | return 0; 20 | } 21 | int zxgb(int a, int b) 22 | { 23 | long int c; 24 | int d; 25 | /*若a 4 | int main() 5 | { 6 | int hun, ten, ind, n; 7 | printf("result is:"); 8 | for( n=100; n<1000; n++ ) /*整数的取值范围*/ 9 | { 10 | hun = n / 100; 11 | ten = (n-hun*100) / 10; 12 | ind = n % 10; 13 | if(n == hun*hun*hun + ten*ten*ten + ind*ind*ind) /*各位上的立方和是否与原数n相等*/ 14 | printf("%d ", n); 15 | } 16 | printf("\n"); 17 | 18 | return 0; 19 | } 20 | 21 | //运行结果: 22 | 23 | //result is:153 370 371 407 24 | -------------------------------------------------------------------------------- /经典项目/求nt的值(3种方法).c: -------------------------------------------------------------------------------- 1 | //求π的近似值,一般有两个公式,如下所示: 2 | 3 | //公式①: 4 | // π/4 ≈ 1 - 1/3 + 1/5 - 1/7 + ... 5 | 6 | //公式②: 7 | // π/2 ≈ 2/1 * 2/3 * 4/3 * 4/5 * 6/5 * 6/7 * ... 8 | 9 | //题目1) 利用公式①计求π的近似值,要求累加到最后一项小于10^(-6)为止。 10 | //题目2) 根据公式②,用前100项之积计算π的值。 11 | //题目1)提供了一种解法,题目2)提供了两种解法,请看解析。 12 | 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | int main(){ 19 | float s=1; 20 | float pi=0; 21 | float i=1.0; 22 | float n=1.0; 23 | while(fabs(i)>=1e-6){ 24 | pi+=i; 25 | n=n+2; 26 | // 这里设计的很巧妙,每次正负号都不一样 27 | s=-s; 28 | i=s/n; 29 | } 30 | pi=4*pi; 31 | printf("pi的值为:%.6f\n",pi); 32 | 33 | return 0; 34 | } 35 | 36 | 37 | //运行结果: 38 | //pi的值为:3.141594 39 | -------------------------------------------------------------------------------- /经典项目/求不重复的3位数.c: -------------------------------------------------------------------------------- 1 | //用1、2、3、4共4个数字能组成多少个互不相同且无重复数字的三位数?都是多少? 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | int i, j, k, count=0; 8 | for(i=1; i<5; i++) 9 | for(j=1; j<5; j++) 10 | for(k=1; k<5; k++) 11 | { 12 | if(i!=k && i!=j && j!=k) /*判断三个数是否互不相同*/ 13 | { 14 | count++; 15 | printf("%d%d%d ", i, j, k); 16 | if(count%8 == 0) /*每输出8个数换行*/ 17 | printf("\n"); 18 | } 19 | } 20 | printf("\nThe total number is %d.\n", count); 21 | 22 | return 0; 23 | } 24 | 25 | 26 | //运行结果: 27 | 28 | //123 124 132 134 142 143 213 214 29 | //231 234 241 243 312 314 321 324 30 | //341 342 412 413 421 423 431 432 31 | // 32 | //The total number is 24. 33 | -------------------------------------------------------------------------------- /经典项目/求亲密数.c: -------------------------------------------------------------------------------- 1 | //如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。 2 | 3 | 4 | #include 5 | int main() 6 | { 7 | int a, i, b, n; 8 | printf("There are following friendly--numbers pair smaller than 3000:\n"); 9 | for( a=1; a<3000; a++ ) /*穷举3000以内的全部整数*/ 10 | { 11 | for( b=0, i=1; i<=a/2; i++) /*计算数a的各因子,各因子之和存放于b*/ 12 | if(!(a%i)) 13 | b+=i; 14 | for( n=0, i=1; i<=b/2; i++ ) /*计算b的各因子,各因子之和存于n*/ 15 | if(!(b%i)) 16 | n+=i; 17 | if(n==a && a 5 | #include 6 | int main() 7 | { 8 | int a, b, c, count=0; 9 | printf("100以内的勾股数有:\n"); 10 | printf(" a b c a b c a b c a b c\n"); 11 | /*求100以内勾股数*/ 12 | for(a=1; a<=100; a++) 13 | for(b=a+1; b<=100; b++) 14 | { 15 | c=(int)sqrt(a*a+b*b); /*求c值*/ 16 | if(c*c==a*a+b*b && a+b>c && a+c>b && b+c>a && c<=100) /*判断c的平方是否等于a2+b2*/ 17 | { 18 | printf("%4d %4d %4d ", a, b, c); 19 | count++; 20 | if(count%4==0) /*每输出4组解就换行*/ 21 | printf("\n"); 22 | } 23 | } 24 | 25 | printf("\n"); 26 | return 0; 27 | } 28 | 29 | 30 | //运行结果: 31 | 32 | /* 33 | 100以内的勾股数有: 34 | a b c a b c a b c a b c 35 | 3 4 5 5 12 13 6 8 10 7 24 25 36 | 8 15 17 9 12 15 9 40 41 10 24 26 37 | 11 60 61 12 16 20 12 35 37 13 84 85 38 | 14 48 50 15 20 25 15 36 39 16 30 34 39 | 16 63 65 18 24 30 18 80 82 20 21 29 40 | 20 48 52 21 28 35 21 72 75 24 32 40 41 | 24 45 51 24 70 74 25 60 65 27 36 45 42 | 28 45 53 28 96 100 30 40 50 30 72 78 43 | 32 60 68 33 44 55 33 56 65 35 84 91 44 | 36 48 60 36 77 85 39 52 65 39 80 89 45 | 40 42 58 40 75 85 42 56 70 45 60 75 46 | 48 55 73 48 64 80 51 68 85 54 72 90 47 | 57 76 95 60 63 87 60 80 100 65 72 97 48 | */ 49 | -------------------------------------------------------------------------------- /经典项目/求回文数.c: -------------------------------------------------------------------------------- 1 | //打印所有不超过n(取n<256)的其平方具有对称性质的数(也称回文数)。 2 | 3 | 4 | #include 5 | int main() 6 | { 7 | int m[16], n, i, t, count=0; 8 | long unsigned a, k; 9 | printf("No. number it's square(palindrome)\n"); 10 | for( n=1; n<256; n++ ) /*穷举n的取值范围*/ 11 | { 12 | k=0; t=1; a=n*n; /*计算n的平方*/ 13 | for( i=0; a!=0; i++ ) /*从低到高分解数a的每一位存于数组m[1]~m[16]*/ 14 | { 15 | m[i] = a % 10; 16 | a /= 10; 17 | } 18 | for(; i>0; i--) 19 | { 20 | k += m[i-1] * t; /*t记录某一位置对应的权值 */ 21 | t *= 10; 22 | } 23 | if(k == n*n) 24 | printf("%2d%10d%10d\n", ++count, n, n*n); 25 | } 26 | return 0; 27 | } 28 | 29 | //运行结果: 30 | 31 | //No. number it's square(palindrome) 32 | //1 1 1 33 | //2 2 4 34 | //3 3 9 35 | //4 11 121 36 | //5 22 484 37 | //6 26 676 38 | //7 101 10201 39 | //8 111 12321 40 | //9 121 14641 41 | //10 202 40804 42 | //11 212 44944 43 | -------------------------------------------------------------------------------- /经典项目/求回文素数.c: -------------------------------------------------------------------------------- 1 | /** 2 | 所谓回文素数指的是,对一个整数n从左向右和从右向左读其数值都相同且n为素数,则称整数为回文素数。 3 | 4 | 对于偶数位的整数,除了11以外,都不存在回文素数。即所有的4位整数、6位整数、 8位整数…都不存在回文素数。下面列出两位和三位整数中包含的所有回文素数。 5 | 6 | 两位回文素数:11 7 | 8 | 三位回文素数:101、131、151、181、191、313、353、373、383、727、757、787、 797、 919、 929 9 | 10 | 本题要求解的问题是:求出所有不超过1000的回文素数。 11 | */ 12 | 13 | #include 14 | 15 | int fun(int n); 16 | 17 | int main() 18 | { 19 | int i, j, k, n, m; 20 | printf("不超过1000的回文数:\n"); 21 | for(i=0; i<=9; ++i) /*穷举第一位*/ 22 | for(j=0; j<=9; ++j) /*穷举第二位*/ 23 | for(k=0; k<=9; ++k) /*穷举第三位*/ 24 | { 25 | n=i*100+j*10+k; /*计算组成的整数*/ 26 | m=k*100+j*10+i; /*计算对应的反序数*/ 27 | if(i==0 && j==0) /*处理整数的前两位为0的情况*/ 28 | { 29 | m=m/100; 30 | } 31 | else if(i==0) /*处理整数的第一位为0的情况*/ 32 | { 33 | m=m/10; 34 | } 35 | if(n>10 && n==m && fun(n)) /*若大于10且为回文素数,则输出*/ 36 | { 37 | printf("%d\t", n); 38 | } 39 | } 40 | printf("\n"); 41 | 42 | return 0; 43 | } 44 | 45 | /*判断参数n是否为素数*/ 46 | int fun(int n) 47 | { 48 | int i; 49 | for(i=2; i<(n-1)/2; ++i) 50 | { 51 | if(n%i == 0) 52 | return 0; 53 | } 54 | return 1; 55 | } 56 | 57 | 58 | //运行结果: 59 | 60 | //不超过1000的回文数: 61 | //11 101 131 151 181 191 313 353 373 383 727 757 787 797 919 929 62 | -------------------------------------------------------------------------------- /经典项目/求多项式之和.c: -------------------------------------------------------------------------------- 1 | /** 2 | 计算下列多项式的值: 3 | 4 | S = 1 + 1/(1*2) + 1/(1*2*3) + ... + 1/(1*2*3* ... * 50) 5 | 6 | 从键盘上输入50后,输出为1.718282。 7 | */ 8 | 9 | #include 10 | int main() 11 | { 12 | double s=0, t; /*s记录多项式的和、t记录每一项分式的分母*/ 13 | int i, n, j; /*n控制项数*/ 14 | printf("please input the number of n:"); /*输入n的值*/ 15 | scanf("%d", &n); 16 | for(i=1; i<=n; i++) /*i控制对应项数*/ 17 | { 18 | t=1; /*每次循环之前给t赋初值*/ 19 | for(j=1; j<=i; j++) 20 | t = t * j; /*求每一项的阶乘*/ 21 | s = s + 1/t; 22 | } 23 | printf("%f\n", s); 24 | 25 | return 0; 26 | } 27 | 28 | 29 | //运行结果 30 | 31 | //please input the number of n:50 32 | //1.718282 33 | -------------------------------------------------------------------------------- /经典项目/求孪生素数.c: -------------------------------------------------------------------------------- 1 | /** 2 | 所谓孪生素数指的是间隔为2的两个相邻素数,因为它们之间的距离已经近的不能再近了,如同孪生兄弟一样,所以将这一对素数称为孪生素数。 3 | 4 | 显然,最小的一对孪生素数是(1,3)。我们可以写出3〜100以内的孪生素数,一共有8对,分别是(3,5),(5,7),(11,13),(17,19), 5 | (29,31),(41,43),(59,61)和(71,73)。随着数字的增大,孪生素数的分布也越来越稀疏,人工寻找孪生素数变得非常困难。 6 | 7 | 本题要解决的问题是:编程求出3〜1000以内的所有孪生素数。 8 | */ 9 | 10 | 11 | #include 12 | #include 13 | 14 | int prime(int n) 15 | { 16 | int j; 17 | long k; 18 | k=sqrt(n)+1; 19 | for(j=2; j<=k; j++) 20 | { 21 | if (n%j == 0) 22 | { 23 | return 0; /*n能被j整除,不是素数,返回0*/ 24 | } 25 | } 26 | return 1; /*n是素数,返回1*/ 27 | } 28 | 29 | int main () 30 | { 31 | int i, count=0; 32 | printf("The twin prime pairs between 3 and 1000 are: \n"); 33 | for (i=3; i<1000; i++) 34 | if( prime(i) && prime(i+2) ) 35 | { 36 | printf("(%-3d,%3d) ", i, i+2); 37 | count++; 38 | if(count%5 == 0) /*变量count控制每行打印的个数,每打印5对孪生素数换行*/ 39 | printf("\n"); 40 | } 41 | 42 | return 0; 43 | } 44 | 45 | 46 | //运行结果: 47 | 48 | //The twin prime pairs between 3 and 1000 are: 49 | //(3 , 5) (5 , 7) (11 , 13) (17 , 19) (29 , 31) 50 | //(41 , 43) (59 , 61) (71 , 73) (101,103) (107,109) 51 | //(137,139) (149,151) (179,181) (191,193) (197,199) 52 | //(227,229) (239,241) (269,271) (281,283) (311,313) 53 | //(347,349) (419,421) (431,433) (461,463) (521,523) 54 | //(569,571) (599,601) (617,619) (641,643) (659,661) 55 | //(809,811) (821,823) (827,829) (857,859) (881,883) 56 | -------------------------------------------------------------------------------- /经典项目/求完数.c: -------------------------------------------------------------------------------- 1 | //求某一范围内完数的个数。 2 | //如果一个数等于它的因子之和,则称该数为“完数”(或“完全数”)。例如,6的因子为1、2、3,而 6=1+2+3,因此6是“完数”。 3 | 4 | 5 | #include 6 | int main() 7 | { 8 | int i, j, s, n; /*变量i控制选定数范围,j控制除数范围,s记录累加因子之和*/ 9 | printf("请输入所选范围上限:"); 10 | scanf("%d", &n); /* n的值由键盘输入*/ 11 | for( i=2; i<=n; i++ ) 12 | { 13 | s=0; /*保证每次循环时s的初值为0*/ 14 | for( j=1; j 4 | int main() 5 | { 6 | int m, n, temp, i; 7 | printf("Input m & n:"); 8 | scanf("%d%d", &m, &n); 9 | if(m0; i--) /*按照从大到小的顺序寻找满足条件的自然数*/ 16 | if(m%i==0 && n%i==0) 17 | {/*输出满足条件的自然数并结束循环*/ 18 | printf("The GCD of %d and %d is: %d\n", m, n, i); 19 | break; 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | //运行结果: 26 | 27 | //Input m & n:100 125 28 | //The GCD of 125 and 100 is: 25 29 | -------------------------------------------------------------------------------- /经典项目/求最小公倍数.c: -------------------------------------------------------------------------------- 1 | //求任意两个正整数的最小公倍数(LCM)。 2 | 3 | #include 4 | int main() 5 | { 6 | int m, n, temp, i; 7 | printf("Input m & n:"); 8 | scanf("%d%d", &m, &n); 9 | if(m0; i++) /*从大数开始寻找满足条件的自然数*/ 16 | if(i%m==0 && i%n==0) 17 | {/*输出满足条件的自然数并结束循环*/ 18 | printf("The LCW of %d and %d is: %d\n", m, n, i); 19 | break; 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | 26 | //运行结果: 27 | 28 | //Input m & n:6 24 29 | //The LCW of 24 and 6 is: 24 30 | -------------------------------------------------------------------------------- /经典项目/求某一年的某一月有多少天问题.c: -------------------------------------------------------------------------------- 1 | //从键盘输入年号和月号,求这一年的这一月共有多少天。 2 | //分析 3 | //这个问题需要考虑闰年问题,因为二月份的天数与闰年有关。闰年的判断依据是:若某年能被4整除,但不能被100整除,则这一年是闰年;若某年能被400整除,则这一年也是闰年。请考虑:闰年如何表达? 4 | 5 | //本题13个分支(比1年12个月共需12个分支多1),编程可使用的多分支结构有哪些?else…if、if…else的嵌套和switch使用哪一个最为简捷?是switch吗? 6 | 7 | 8 | #include 9 | #include 10 | 11 | void main(){ 12 | int year, month, days; 13 | 14 | printf("输入年份:"); 15 | scanf("%d",&year); 16 | printf("输入月份:"); 17 | scanf("%d", &month); 18 | 19 | switch(month){ 20 | case 1: 21 | case 3: 22 | case 5: 23 | case 7: 24 | case 8: 25 | case 10: 26 | case 12: 27 | days=31; 28 | break; 29 | case 4: 30 | case 6: 31 | case 9: 32 | case 11: 33 | days=30; 34 | break; 35 | case 2: 36 | // 判断闰年 37 | if(year%4==0 && year%100!=0 || year%400==0) 38 | days=29; 39 | else 40 | days=28; 41 | break; 42 | default: 43 | printf("月份输入错误!\n"); 44 | exit(1); 45 | break; 46 | } 47 | printf("天数:%d\n", days); 48 | } 49 | 50 | 51 | //第一次运行结果: 52 | //输入年份:2014 53 | //输入月份:10 54 | //天数:31 55 | 56 | //第二次运行结果: 57 | //输入年份:2013 58 | //输入月份:02 59 | //天数:28 60 | 61 | //第三次运行结果: 62 | //输入年份:2000 63 | //输入月份:2 64 | //天数:29 65 | -------------------------------------------------------------------------------- /经典项目/求梅森素数.c: -------------------------------------------------------------------------------- 1 | /** 2 | 梅森数(Mersenne Prime)指的是形如2n-1的正整数,其中指数n是素数,即为Mn。如果一个梅森数是素数,则称其为梅森素数。例如22-1=3、23-1=7都是梅森素数。 3 | 4 | 当n=2,3,5,7时,Mn 都是素数,但n=11时,Mn=M11=211-1=2047=23X89,显然不是梅森素数。 5 | 6 | 1722年,瑞士数学大师欧拉证明了231-1=2147483647是一个素数,它共有10位数,成为当时世界上已知的最大素数。 7 | 8 | 迄今为止,人类仅发现了47个梅森素数。梅森素数历来都是数论研究中的一项重要内容,也是当今科学探索中的热点和难点问题。 9 | 10 | 试求出指数n<20的所有梅森素数。 11 | */ 12 | 13 | #include 14 | #include 15 | int prime(int n) 16 | { 17 | int i; 18 | long k; 19 | k=sqrt(n)+1; 20 | for(i=2; i<=k; i++) 21 | if(n%i == 0) 22 | return 0; 23 | return 1; 24 | } 25 | int main() 26 | { 27 | int mp, n=0, i; 28 | printf("Mersenne Prime:\n"); 29 | for(i=2; i<=20; i++) 30 | { 31 | mp=pow(2,i)-1; 32 | if( prime(mp) ) 33 | { 34 | n++; 35 | printf("M(%d)=%d", i, mp); 36 | printf("\n"); 37 | } 38 | } 39 | printf("the number of Mersenne Prime less than 20 is:%d\n", n); 40 | 41 | return 0; 42 | } 43 | 44 | 45 | //运行结果: 46 | 47 | //Mersenne Prime: 48 | //M(2)=3 49 | //M(3)=7 50 | //M(5)=31 51 | //M(7)=127 52 | //M(13)=8191 53 | //M(17)=131071 54 | //M(19)=524287 55 | //the number of Mersenne Prime less than 20 is:7 56 | -------------------------------------------------------------------------------- /经典项目/求给定范围内的所有素数.c: -------------------------------------------------------------------------------- 1 | //求给定范围start〜end之间的所有素数。 2 | 3 | #include 4 | #include 5 | int main() 6 | { 7 | int start, end, i, k, m, flag=1, h=0; 8 | do 9 | { 10 | printf("Input START and END:"); 11 | scanf("%d%d", &start, &end); 12 | }while(!(start>0 && start 9 | int main() 10 | { 11 | long mul, number, k, a, b; 12 | printf("It exists following automorphic nmbers small than 100000:\n"); 13 | for( number=0; number<100000; number++ ) 14 | { 15 | for( mul=number, k=1; (mul/=10)>0; k*=10 ); 16 | /*由number的位数确定截取数字进行乘法时的系数k*/ 17 | a = k * 10; /*a为截取部分积时的系数*/ 18 | mul = 0; /*积的最后n位*/ 19 | b = 10; /*b为截取乘数相应位时的系数*/ 20 | while(k>0) 21 | { 22 | mul=( mul + ( number%(k*10) )*( number%b - number%(b/10) ) )%a; 23 | /*(部分积+截取被乘数的后N位*截取乘数的第M位),%a再截取部分积*/ 24 | k /= 10; /*k为截取被乘数时的系数*/ 25 | b *= 10; 26 | } 27 | if(number == mul) /*判定若为自守数则输出*/ 28 | printf("%ld ", number); 29 | } 30 | printf("\n"); 31 | 32 | return 0; 33 | } 34 | 35 | //运行结果: 36 | 37 | //It exists following automorphic nmbers small than 100000: 38 | //0 1 5 6 25 76 376 625 9376 90625 39 | -------------------------------------------------------------------------------- /经典项目/求车速.c: -------------------------------------------------------------------------------- 1 | //一辆以固定速度行驶的汽车,司机在上午10点看到里程表上的读数是一个对称数(即这个数从左向右读和从右向左读是完全一样的),为95859。 2 | //两小时后里程表上出现了一个新的对称数,该数仍为五位数。问该车的速度是多少?新的对称数是多少? 3 | 4 | #include 5 | int main() 6 | { 7 | int t, a[5]; /*数组a存放分解后的五个数字*/ 8 | long int k, i; 9 | /*以95860为初值,循环试探*/ 10 | for(i=95860; ; i++) 11 | { 12 | /*从高到低分解当前i中保存的五位数,并顺次存放在数组元素a[0]~a[4]中*/ 13 | for(t=0,k=100000; k>=10; t++) 14 | { 15 | a[t] = (i%k) / (k/10); 16 | k /= 10; 17 | } 18 | if( (a[0]==a[4]) && (a[1]==a[3]) ) 19 | { 20 | printf("里程表上出现的新的对称数为:%d%d%d%d%d\n", 21 | a[0], a[1], a[2], a[3], a[4] ); 22 | printf("该车的速度为:%.2f\n", (i-95859)/2.0); 23 | break; /*跳出循环*/ 24 | } 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | 31 | //运行结果: 32 | 33 | //里程表上出现的新的对称数为:95959 34 | //该车的速度为:50.00 35 | -------------------------------------------------------------------------------- /经典项目/求高次方数的尾数.c: -------------------------------------------------------------------------------- 1 | //求13的13次方的最后三位数。 2 | 3 | #include 4 | int main() 5 | { 6 | int i, x, y, last=1; /*变量last保存求得的x的y次方的部分积的后三位*/ 7 | printf("Input x and y:\n"); 8 | scanf("%d %d", &x, &y); 9 | for(i=1; i<=y; i++) /*x自乘的次数y*/ 10 | last = last * x % 1000; /*将last乘x后对1000取模,即求积的后三位*/ 11 | printf("The last three digits is:%d\n", last); 12 | 13 | return 0; 14 | } 15 | 16 | //运行结果: 17 | 18 | //Input x and y: 19 | //13 13 20 | //The last three digits is:253 21 | -------------------------------------------------------------------------------- /经典项目/求黑洞数.c: -------------------------------------------------------------------------------- 1 | /** 2 | 编程求三位数中的“黑洞数”。 3 | 4 | 黑洞数又称陷阱数,任何一个数字不全相同的整数,经有限次“重排求差”操作,总会得到某一个或一些数,这些数即为黑洞数。 5 | “重排求差”操作是将组成一个数的各位数字重排得到的最大数减去最小数, 6 | 例如207,“重排求差”操作序列是720-027=693,963-369=594,954-459=495,再做下去就不变了,再用208算一次,也停止到495, 7 | 所以495是三位黑洞数。 8 | */ 9 | 10 | 11 | #include 12 | int maxof3(int, int, int); 13 | int minof3(int, int, int); 14 | int main() 15 | { 16 | int i, k; 17 | int hun, oct, data, max, min, j, h; 18 | printf("请输入一个三位数:"); 19 | scanf("%d", &i); 20 | hun=i/100; 21 | oct=i%100/10; 22 | data=i%10; 23 | max=maxof3(hun, oct, data); 24 | min=minof3(hun, oct, data); 25 | j=max-min; 26 | for(k=0; ; k++) /*k控制循环次数*/ 27 | { 28 | h=j; /*h记录上一次最大值与最小值的差*/ 29 | hun=j/100; 30 | oct=j%100/10; 31 | data=j%10; 32 | max=maxof3(hun, oct, data); 33 | min=minof3(hun, oct, data); 34 | j=max-min; 35 | if(j==h) /*最后两次差相等时,差即为所求黑洞数*/ 36 | { 37 | printf("%d\n", j); 38 | break; /*跳出循环*/ 39 | } 40 | } 41 | return 0; 42 | } 43 | /*求三位数重排后的最大数*/ 44 | int maxof3(int a,int b,int c) 45 | { 46 | int t; 47 | if(a 5 | int main() 6 | { 7 | long n, sum, i; 8 | int flag=1; 9 | while(flag) 10 | { 11 | printf("输入N:"); 12 | scanf("%ld", &n); 13 | printf("在1-%ld之间的阶梯数为:\n", n); 14 | sum=0; 15 | for( i=7; i<=n; i++ ) 16 | if( i%7 == 0 ) 17 | if( i%6 == 5 ) 18 | if( i%5 == 4 ) 19 | if( i%3 == 2 ) 20 | { 21 | sum++; 22 | printf("%ld\n", i); 23 | } 24 | printf("在1-%ld之间,有%ld个数可以满足爱因斯坦对阶梯的要求。\n", n, sum); 25 | printf("继续请输入1,否则输入0:\n"); 26 | scanf("%d", &flag); 27 | 28 | } 29 | return 0; 30 | } 31 | 32 | 33 | //运行结果: 34 | 35 | /* 36 | 输入N:123 37 | 在1-123之间的阶梯数为: 38 | 119 39 | 在1-123之间,有1个数可以满足爱因斯坦对阶梯的要求。 40 | 继续请输入1,否则输入0: 41 | 1 42 | 输入N:1234 43 | 在1-1234之间的阶梯数为: 44 | 119 45 | 329 46 | 539 47 | 749 48 | 959 49 | 1169 50 | 在1-1234之间,有6个数可以满足爱因斯坦对阶梯的要求。 51 | 继续请输入1,否则输入0: 52 | */ 53 | -------------------------------------------------------------------------------- /经典项目/牛顿迭代法求方程根.c: -------------------------------------------------------------------------------- 1 | //编写用牛顿迭代法求方程根的函数。方程为,系数a、b、c、d由主函数输入。求x在1附近的一个实根。求出根后,由主函数输出。 2 | 3 | //牛顿迭代法的公式是:,设迭代到 时结束。 4 | 5 | 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | /*函数功能是用牛顿迭代法求方程的根*/ 12 | float solution( float a, float b, float c, float d); 13 | float a, b, c, d, x; /*a,b,c,d代表所求方程的系数,x用来记录求得的方程根*/ 14 | printf("请输入方程的系数:"); 15 | scanf("%f %f %f %f", &a, &b, &c, &d); 16 | x = solution(a, b, c, d); 17 | printf("所求方程的根为x=%f", x); 18 | 19 | return 0; 20 | } 21 | 22 | float solution(float a, float b, float c, float d) 23 | { 24 | float x0, x=1.5, f, fd, h; /*f用来描述方程的值,fd用来描述方程求导之后的值*/ 25 | do 26 | { 27 | x0 = x; /*用所求得的x的值代替x0原来的值*/ 28 | f = a*x0*x0*x0 + b*x0*x0 + c*x0 + d; 29 | fd = 3*a*x0*x0 + 2*b*x0 + c; 30 | h = f / fd; 31 | x = x0 - h; /*求得更接近方程根的x的值*/ 32 | } 33 | while(fabs(x-x0) >= 1e-5); 34 | 35 | return x; 36 | } 37 | 38 | //运行结果: 39 | 40 | //请输入方程的系数:2 -3 4 -2 41 | //所求方程的根为x=0.694146 42 | -------------------------------------------------------------------------------- /经典项目/狼追兔子.c: -------------------------------------------------------------------------------- 1 | /** 2 | 一只兔子躲进了10个环形分布的洞中的一个。狼在第一个洞中没有找到兔子,就隔一个洞,到第3个洞去找; 3 | 也没有找到,就隔2个洞,到第6个洞去找;以后每次多一个洞去找兔子……这样下去,如果一直找不到兔子, 4 | 请问兔子可能在哪个洞中? 5 | */ 6 | 7 | 8 | #include 9 | int main() 10 | { 11 | int n=0, i=0, x=0; 12 | int a[11]; 13 | for(i=0; i<11; i++) /*设置数组初值*/ 14 | a[i]=1; 15 | for(i=0; i<1000; i++) /*穷举搜索*/ 16 | { 17 | n+=(i+1); 18 | x=n%10; 19 | a[x]=0; /*未找到,置0*/ 20 | } 21 | for(i=0; i<10; i++) /*输出结果*/ 22 | { 23 | if(a[i]) 24 | printf("可能在第%d个洞\n", i); 25 | } 26 | return 0; 27 | } 28 | 29 | //运行结果: 30 | 31 | //可能在第2个洞 32 | //可能在第4个洞 33 | //可能在第7个洞 34 | //可能在第9个洞 35 | -------------------------------------------------------------------------------- /经典项目/猜牌术.c: -------------------------------------------------------------------------------- 1 | //魔术师利用一副牌中的13张黑桃,预先将它们排好后迭在一起,并使牌面朝下。然后他对观众说:我不看牌,只要数数就可以猜到每张牌是什么,我大声数数,你们听,不信? 2 | //你们就看,魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,他将黑桃A放在桌子上,然后按顺序从上到下数手中的余牌,第二次数1、2,将第一张牌放在这迭牌的下面, 3 | //将第二张牌翻过来,正好是黑桃2,也将它放在桌子上,第三次数1、2、3,将前面两张依次放在这迭牌的下面,再翻第三张牌正好是黑桃3,这样依次进行,将13张牌全部翻出来, 4 | //准确无误。问魔术师手中的牌原始次序是怎样安排的? 5 | 6 | 7 | #include 8 | 9 | int a[14]; 10 | 11 | int main() 12 | { 13 | int i, j=1, n; 14 | printf("魔术师手中的牌原始次序是:\n"); 15 | for( i=1; i<=13; i++ ) 16 | { 17 | n=1; 18 | do 19 | { 20 | if(j>13) 21 | j=1; 22 | if(a[j]) /*盒子非空*/ 23 | j++; 24 | else /*盒子为空*/ 25 | { 26 | if(n==i) 27 | a[j]=i; 28 | j++; 29 | n++; 30 | } 31 | } 32 | while(n<=i); 33 | } 34 | for( i=1; i<=13; i++ ) 35 | printf("%d ", a[i]); 36 | printf("\n"); 37 | 38 | return 0; 39 | } 40 | 41 | 42 | //运行结果: 43 | 44 | //魔术师手中的牌原始次序是: 45 | //1 8 2 5 10 3 12 11 9 4 7 6 13 46 | -------------------------------------------------------------------------------- /经典项目/猴子吃桃问题.c: -------------------------------------------------------------------------------- 1 | //猴子第一天摘了若干个桃子,当即吃了一半,还不解馋,又多吃了一个;第二天,吃剩下的桃子的一半,还不过瘾,又多吃了一个;以后每天都吃前一天剩下的一半多一个,到第10天想再吃时,只剩下一个桃子了。问第一天共摘了多少个桃子? 2 | //分析 3 | //1) 设x1为前一天桃子数,设x2为第二天桃子数, 则: 4 | // x2=x1/2-1, x1=(x2+1)*2 5 | // x3=x2/2-1, x2=(x3+1)*2 6 | // 以此类推: x前=(x后+1)*2 7 | 8 | //2) 从第10天可以类推到第1天,是一个循环过程。 9 | 10 | 11 | #include 12 | #include 13 | 14 | int main(){ 15 | int day, x1, x2; 16 | day=9; 17 | x2=1; 18 | while(day>0) { 19 | x1=(x2+1)*2; // 第一天的桃子数是第2天桃子数加1后的2倍 20 | x2=x1; 21 | day--; 22 | } 23 | printf("the total is %d\n",x1); 24 | 25 | return 0; 26 | } 27 | 28 | //运行结果: 29 | 30 | //the total is 1534 31 | -------------------------------------------------------------------------------- /经典项目/百钱百鸡问题.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/矩阵转置.c: -------------------------------------------------------------------------------- 1 | //编写一个程序,将一个3行3列的矩阵转置。 2 | 3 | #include 4 | int main() 5 | { 6 | int n[3][3]={1, 2, 3, 4, 5, 6, 7, 8, 9}; 7 | int i, j, temp; 8 | printf("原始矩阵:\n"); 9 | for(i=0; i<3; i++) 10 | { 11 | for(j=0; j<3; j++) 12 | printf("%d ", n[i][j]); /*输出原始矩阵*/ 13 | printf("\n"); 14 | } 15 | for(i=0; i<3; i++) 16 | for(j=0; j<3; j++) 17 | { 18 | if (j>i) 19 | { /*将主对角线右上方的数组元素与主对角线左下方的数组元素进行单方向交换*/ 20 | temp=n[i][j]; 21 | n[i][j]=n[j][i]; 22 | n[j][i]=temp; 23 | } 24 | } 25 | printf("转置矩阵:\n"); 26 | for(i=0; i<3; i++) 27 | { 28 | for(j=0; j<3; j++) 29 | printf("%d ", n[i][j]); /*输出原始矩阵的转置矩阵*/ 30 | printf("\n"); 31 | } 32 | return 0; 33 | } 34 | 35 | 36 | //运行结果: 37 | 38 | //原始矩阵: 39 | //1 2 3 40 | //4 5 6 41 | //7 8 9 42 | //转置矩阵: 43 | //1 4 7 44 | //2 5 8 45 | //3 6 9 46 | -------------------------------------------------------------------------------- /经典项目/线性同余法产生随机数.c: -------------------------------------------------------------------------------- 1 | //线性同余法产生随机数序列的公式为: 2 | // x[k+1] = (a*x[k] + c) % m 3 | 4 | //参数 a, c, m 都是由用户来设定的,并和一个种子数(例如 x[0])一起作为命令行参数传递给生成的程序。 5 | 6 | //一个简单的例子:a=7, c=1, m=13, and seed=5 7 | 8 | //一个复杂的例子:a=69069, c=0, m=2^32=4294967296, seed=31 9 | 10 | //下面的代码将输出一个随机数序列(最多有 m-1 个不同的值),然后继续循环。 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | static long seed = 13; 19 | static long a; 20 | static long c; 21 | static long m; 22 | 23 | void random_init(long s) { 24 | if (s != 0) seed = s; 25 | } 26 | 27 | long random() { 28 | seed = (a*seed + c)%m; 29 | return seed; 30 | } 31 | 32 | int main(int argc, char * argv[]) { 33 | long s; 34 | int k; 35 | if (argc != 5) { 36 | printf("usage: %s a, c, m, seed\n", argv[0]); 37 | return 1; 38 | } 39 | a = atoi(argv[1]); 40 | c = atoi(argv[2]); 41 | m = atoi(argv[3]); 42 | s = atoi(argv[4]); 43 | random_init(s); 44 | 45 | for (k = 0; k < m-1; k++) { 46 | printf("%8ld", random()); 47 | if (k % 8 == 7) { // 输出 8 个数字以后换行 48 | printf("\n"); 49 | Sleep(1); // 暂停 1 秒 50 | } 51 | } 52 | printf("\n"); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /经典项目/统计文件中单词的个数.c: -------------------------------------------------------------------------------- 1 | ///文本检索是软件最常用的一个功能,用C语言写一段程序,统计某个文件中单词的个数。 2 | //提示:单词是以空格为分隔的。 3 | //文本检索是软件最常用的一个功能,下面的代码将教你如果使用C语言统计单词的个数。 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // argc: 统计运行程序时命令行参数的个数 11 | // *argv[]: 储存每个参数的字符串指针,每一个元素对应一个参数 12 | int main (int argc,char *argv[]) 13 | { 14 | int ch,bian=0,count=0; 15 | char find[50],temp[1000]; 16 | FILE *pt; //文件指针 17 | 18 | // 判断是否输入文件 19 | if (argc != 2){ 20 | printf("请使用格式: %s 文件名",argv[0]); 21 | exit(1); //非正常退出 22 | } 23 | 24 | // 判断能否成功打开文件 25 | if ((pt = fopen(argv[1],"r"))== NULL){ //将argv[1]赋值给指针pt 26 | printf("打开文件 %s 失败",argv[1]); 27 | exit(1); 28 | } 29 | 30 | printf("请输入要查找的单词:"); 31 | gets(find); 32 | while((ch=getc(pt))!=EOF){ //EOF 表示文件结束 33 | if ((ch!=' ')&&(ch!='\n')){ 34 | temp[bian]=ch; 35 | bian++; 36 | } else { 37 | temp[bian]='\0'; 38 | if ((strcmp(find,temp))==0) count++; 39 | bian=0; 40 | } 41 | } 42 | printf("共在文件%s中查找到字符串\"%s\" %d 个\n",argv[1],find,count); 43 | 44 | getch(); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /经典项目/统计英文字母、空格、数字和其它字符的数目.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | char c; //用户输入的字符 5 | int letters=0, // 字母数目 6 | space=0, // 空格数目 7 | digit=0, // 整数数目 8 | others=0; // 其他字符数目 9 | 10 | printf("输入一些字符:"); 11 | while((c=getchar())!='\n'){ // 每次读取一个字符,回车时结束 12 | if(c>='a'&&c<='z'||c>='A'&&c<='Z') 13 | letters++; 14 | else if(c==' ') 15 | space++; 16 | else if(c>='0'&&c<='9') 17 | digit++; 18 | else 19 | others++; 20 | } 21 | 22 | printf("\n统计结果:\n英文字母=%d\n空格=%d\n整数=%d\n其他字符=%d\n\n", letters, space, digit, others); 23 | 24 | return 0; 25 | } 26 | 27 | 28 | //运行结果: 29 | 30 | //输入一些字符:rwrwewre2345asdJSJQI%^&(& *&sdf YY( 2342-k' 31 | 32 | //统计结果: 33 | //英文字母=22 34 | //空格=5 35 | //整数=8 36 | //其他字符=10 37 | -------------------------------------------------------------------------------- /经典项目/统计输入的字符串的长度.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | char str[21]; 6 | int strLen; 7 | 8 | printf("Input your string: "); 9 | scanf("%s", str); 10 | strLen = strlen(str); 11 | printf("string = %s\nlength = %d\n", str, strLen); 12 | 13 | return 0; 14 | } 15 | 16 | 17 | //运行结果: 18 | 19 | //Input your string: 1234567890 20 | //string = 1234567890 21 | //length = 10 22 | //---------------------------------- 23 | //Input your string: 123456 7890 24 | //string = 123456 25 | //length = 6 26 | //---------------------------------- 27 | //Input your string: 1234567890123456789012345 28 | //string = 1234567890123456789012345 29 | //length = 25 30 | // 提示程序停止运行 31 | -------------------------------------------------------------------------------- /经典项目/舍罕王的失算.c: -------------------------------------------------------------------------------- 1 | //相传国际象棋是古印度舍罕王的宰相达依尔发明的。舍罕王十分喜爱象棋,决定让宰相自己选择何种赏赐。这位聪明的宰相指着 8×8 共64格的象棋棋盘说:陛下,请您赏给我一些麦子吧。就在棋盘的第1格中放1粒,第2格放2粒,第3格放4粒,以后每一格都比前一格增加一倍,依此放完棋盘上64格,我就感激不尽了。舍罕王让人扛来一袋麦子,他要兑现他的许诺。请编程求出国王总共需要将多少麦子赏赐给他的宰相。 2 | 3 | //该问题描述比较复杂,但只要抽象出其数学模型,便很容易解决了。 4 | 5 | //根据题意,麦子的放法是:在棋盘的第1格中放1粒,第2格放2粒,第3格放4粒,以后每一格都比前一格增加一倍,依次放完棋盘上64格。 6 | 7 | //由此可推知,按照如此放法可得到的麦子的总数为: 8 | 9 | //2^0 + 2^1 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + ... + 2^63 = ? 10 | 11 | 12 | #include 13 | #include 14 | int main() 15 | { 16 | double sum = 0; /*定义double型变量sum存放累加和*/ 17 | int i; 18 | /*使用循环求累加和*/ 19 | for( i=1; i<=64; i++ ) 20 | sum = sum + pow(2.0, (i-1)); /*注意变量为double型*/ 21 | printf("国王总共需要赏赐给宰相的麦子数为:\n%f\n", sum); /*打印结果*/ 22 | return 0; 23 | } 24 | 25 | 26 | //运行结果: 27 | 28 | //国王总共需要赏赐给宰相的麦子数为: 29 | //18446744073709551616.000000 30 | -------------------------------------------------------------------------------- /经典项目/获取开机时间.c: -------------------------------------------------------------------------------- 1 | //这个其实不难,就是用到一个简单的Windows API,代码请见解析。 2 | 3 | //获取开机时间要用到 GetTickCount() 这个 API,功能是获取重系统开始到运行时的时间。代码如下: 4 | 5 | 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | DWORD k = GetTickCount(); 12 | int s = k/1000; 13 | int min = 0, h = 0; 14 | if (s >= 60){ 15 | min = s / 60; 16 | s = s % 60; 17 | } 18 | if (min >= 60){ 19 | h = min / 60; 20 | min = min % 60; 21 | } 22 | printf("重系统启动到现在过了的时间:%d h %d min %d s\n",h,min,s); 23 | 24 | system("pause"); 25 | return 0; 26 | } 27 | 28 | //运行结果: 29 | //重系统启动到现在过了的时间:40 h 20 min 33 s 30 | //请按任意键继续. . . 31 | -------------------------------------------------------------------------------- /经典项目/要发就发(1898)问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | “1898—要发就发”。请将不超过1993的所有素数从小到大排成第一行,第二行上的每个数都等于它上面相邻两个素数之差。 3 | 编程求出:第二行数中是否存在若干个连续的整数,它们的和恰好为1898?假如存在的话,又有几种这样的情况? 4 | 5 | 两行数据分别如下: 6 | 第一行:2 3 5 7 11 13 17......1979 1987 1993 7 | 第二行:1 2 2 4 2 4......8 6 8 | */ 9 | 10 | 11 | #include 12 | #include 13 | 14 | #define NUM 320 15 | 16 | int number[NUM]; /*存放不超过1993的全部素数*/ 17 | int fun(int i); 18 | 19 | int main() 20 | { 21 | int i, j, count=0; 22 | printf("列出第一行中差值为1989的所有素数组合:\n"); 23 | for(j=0, i=3; i<=1993; i+=2) /*求出不超过1993的全部素数*/ 24 | if( fun(i) ) 25 | number[j++]=i; 26 | for(j--; number[j]>1898; j--) /*从最大的素数开始向1898搜索*/ 27 | { 28 | for(i=0; number[j]-number[i]>1898; i++); /*循环查找满足条件的素数*/ 29 | if(number[j]-number[i] == 1898) /*若两个素数的差为1898,则输出*/ 30 | printf("(%d).%3d,%d\n", ++count, number[i], number[j]); 31 | } 32 | 33 | return 0; 34 | } 35 | 36 | int fun(int i) 37 | { 38 | int j; 39 | if( i<=1 ) 40 | return 0; /*判断是否为素数,为1是素数,为0不是素数*/ 41 | if( i==2 ) 42 | return 1; 43 | if( !(i%2) ) 44 | return 0; /*if no, return 0*/ 45 | for(j=3; j<=(int)(sqrt((double)i)+1); j+=2) 46 | if( !(i%j) ) return 0; 47 | return 1; 48 | } 49 | 50 | 51 | //运行结果: 52 | 53 | //列出第一行中差值为1989的所有素数组合: 54 | //(1). 89,1987 55 | //(2). 53,1951 56 | (3). 3,1901 57 | -------------------------------------------------------------------------------- /经典项目/计算一个数的平方根.c: -------------------------------------------------------------------------------- 1 | //正数n的平方根可以通过计算一系列近似值来获得,每个近似值都比前一个更加接近准确值。第一个近似值是1,接下来的近似值则通过下面的公式来获得。 2 | 3 | 4 | //编写一个程序,读入一个值,计算并打印出它的平方根。如果你将所有的近似值都打印出来,你会发现这种方法获得准确结果的速度有多快。原则上,这种计算可以永远进行下去,它会不断产生更加精确的结果。但在实际中,由于浮点变量的精度限制,程序无法一直计算下去。当某个近似值与前一个近似值相等时,你就可以让程序停止继续计算了。 5 | 6 | //必须使用浮点变量,而且程序应该对负值输入进行检查。 7 | 8 | 9 | // 计算一个数的平方根。 10 | #include 11 | #include 12 | 13 | int main(){ 14 | float new_guess; 15 | float last_guess; 16 | float number; 17 | 18 | // 催促用户输入,读取数据并对它进行检查。 19 | printf("Enter a number: " ); 20 | scanf("%f", &number ); 21 | if( number < 0 ){ 22 | printf("Cannot compute the square root of a " "negative number! \n"); 23 | return EXIT_FAILURE; 24 | } 25 | 26 | // 计算平方根的近似值,直到它的值不再变化。 27 | new_guess = 1; 28 | do{ 29 | last_guess = new_guess; 30 | new_guess = ( last_guess + number / last_guess ) / 2; 31 | printf ("%.15e\n", new_guess ); 32 | } while( new_guess != last_guess ); 33 | 34 | // 打印结果 35 | printf ("Square root of %g is %g\n", number, new_guess ); 36 | return EXIT_SUCCESS; 37 | } 38 | -------------------------------------------------------------------------------- /经典项目/计算你收藏的硬币值多少钱.c: -------------------------------------------------------------------------------- 1 | //美国的货币单位为美元(Dollar),1美元等于100美分。纸币面额最小为1美元,1美元以下用硬币,硬币有25美分(Quarter)、10美分(Dime,一角)、5美分(Nickel)、1美分(Cent 或 penny)。 2 | 3 | //下面的程序要求输入你收藏的 1美分( penny)、5美分(Nickel)、10美分(Dime)、25美分(Quarter)的硬币的数量,然后对他们进行计算。 4 | 5 | 6 | #include 7 | 8 | void main () 9 | { 10 | // 设置变量 11 | int pennies; // 1美分硬币的数量 12 | int nickels; // 5美分硬币的数量 13 | int dimes; // 10美分硬币的数量 14 | int quarters; // 25美分硬币的数量 15 | int temp, left; // 临时变量,将会用于各种计算 16 | 17 | // 输入 1美分( penny)、5美分(Nickel)、10美分(Dime)、25美分(Quarter)的硬币的数量 18 | printf("Enter the number of quarters, dimes, nickels, and pennies: "); 19 | scanf("%d %d %d %d", &quarters, &dimes, &nickels, &pennies); 20 | 21 | // 以美分(Cent)为单位计算硬币的价值 22 | left = 25 * quarters + 10 * dimes + 5 * nickels + pennies; 23 | 24 | // 转换成dollar(美元) 25 | printf("Your collection is worth\n "); 26 | temp = left / 100; 27 | printf("\t%d dollar", temp); 28 | if (temp==1) 29 | printf(", "); 30 | else 31 | printf("s, "); 32 | left = left % 100; 33 | 34 | // 转换成quarter(25美分) 35 | temp = left / 25; 36 | printf("%d quarter", temp); 37 | if (temp==1) 38 | printf(", "); 39 | else 40 | printf("s, "); 41 | left = left % 25; 42 | 43 | // 转换成dime(10美分) 44 | temp = left / 10; 45 | printf("%d dime", temp); 46 | 47 | // 这里本来应该使用条件语句,不过我使用了条件表达式和字符串连接 48 | printf ((temp==1) ? ", " : "s, "); 49 | left = left % 10; 50 | 51 | // 转换成nickel(5美分) 52 | temp = left / 5; 53 | printf("%d nickel", temp); 54 | if (temp==1) 55 | printf(", and "); 56 | else 57 | printf("s, and "); 58 | left = left % 5; 59 | 60 | // 转换成penny(1美分) 61 | printf("%d penn", left); 62 | if (left==1) 63 | printf("y\n"); 64 | else 65 | printf("ies\n"); 66 | } 67 | 68 | //输出结果类似: 69 | //Enter the number of quarters, dimes, nickels, and pennies: 100 23 62 89 70 | //Your collection is worth 71 | // 31 dollars, 1 quarter, 0 dimes, 0 nickels, and 4 pennies 72 | -------------------------------------------------------------------------------- /经典项目/计算分数的精确值.c: -------------------------------------------------------------------------------- 1 | //使用数组精确计算M/N(0 4 | int main() 5 | { 6 | int m, n, i, j; 7 | int remainder[101]={0}, quotient[101]={0}; 8 | /*remainder:存放除法的余数; quotient:依次存放商的每一位*/ 9 | printf("Please input a fraction(m/n)(<0 2 | 3 | /** 4 | * 计算 Hermite polynomial 的值 5 | * 6 | * 输入: 7 | * n, x:用于标识值 8 | * 9 | * 输出: 10 | * polynomial的值(返回值) 11 | **/ 12 | 13 | int hermite( int n, int x ) 14 | { 15 | // 处理不需要递归的特殊情况。 16 | if( n <= 0 ) 17 | return 1; 18 | if( n == 1 ) 19 | return 2 * x; 20 | 21 | // 否则,递归地计算结果值。 22 | return 2 * x * hermite( n - l, x ) - 2 * ( n - 1 ) * hermite ( n - 2, x ); 23 | } 24 | 25 | int main() 26 | { 27 | printf("%d\n", hermite(3,2)); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /经典项目/计算用1分钱、2分钱、5分钱组成1元钱的方式.c: -------------------------------------------------------------------------------- 1 | //用1分钱、2分钱、5分钱组成1元钱,请给出所有的组合方式。 2 | 3 | #include 4 | int main(){ 5 | int m, n, k=0; 6 | for(m=0; m<=100/5; m++) 7 | for(n=0; n<=(100-5*m)/2; n++){ 8 | printf("1分%d个,2分%d个,5分%d个\n", 100-5*m-2*n, n, m); 9 | k++; 10 | } 11 | printf("共有%d种组合方式\n", k); 12 | return 0; 13 | } 14 | 15 | //运行结果: 16 | //...... 17 | //5分0个,2分6个,1分88个 18 | //5分0个,2分5个,1分90个 19 | //5分0个,2分4个,1分92个 20 | //5分0个,2分3个,1分94个 21 | //5分0个,2分2个,1分96个 22 | //5分0个,2分1个,1分98个 23 | //5分0个,2分0个,1分100个 24 | //共有541种组合方式 25 | -------------------------------------------------------------------------------- /经典项目/谁在说谎问题.c: -------------------------------------------------------------------------------- 1 | //现有张三、李四和王五3个人,张三说李四在说谎,李四说王五在说谎,而王五说张三和李四两人都在说谎。要求编程求出这3个人中到底谁说的是真话,谁说的是假话。 2 | 3 | #include 4 | int main() 5 | { 6 | int x, y, z; 7 | for(x=0; x<=1; x++) 8 | for(y=0; y<=1; y++) 9 | for(z=0; z<=1; z++) 10 | if( ((x&&!y) || (!x&&y)) && ((y&&!z) || (!y&&z)) && ((z&&x==0&&y==0) || (!z&&x+y!=0)) ) 11 | { 12 | printf("张三说的是%s.\n",x?"真话":"假话"); 13 | printf("李四说的是%s.\n",y?"真话":"假话"); 14 | printf("王五说的是%s.\n",z?"真话":"假话"); 15 | 16 | } 17 | return 0; 18 | } 19 | 20 | //运行结果: 21 | 22 | //张三说的是假话. 23 | //李四说的是真话. 24 | //王五说的是假话. 25 | -------------------------------------------------------------------------------- /经典项目/谁是窃贼问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | 警察审问4名窃贼嫌疑犯。现在已知,这4人当中仅有一名是窃贼,还知道这4个人中的每个人要么是诚实的,要么总是说谎。 3 | 4 | 这4个人给警察的回答如下。 5 | 甲说:“乙没有偷,是丁偷的。” 6 | 乙说:“我没有偷,是丙偷的。” 7 | 丙说:“甲没有偷,是乙偷的。” 8 | 丁说:“我没有偷。” 9 | 10 | 请根据这4个人的回答判断谁是窃贼。 11 | */ 12 | 13 | #include 14 | int main() 15 | { 16 | int i, A=1, B=0, C=0, D=0; /*先假定甲是窃贼*/ 17 | for(i=1; i<=4; i++) 18 | if(B+D==1 && B+C==1 && A+B==1) /*测试甲乙丙丁谁是窃贼,符合该条件的即为窃贼*/ 19 | break; 20 | else 21 | { 22 | if(i == 1) 23 | { 24 | A=0; /*甲不是窃贼,测试乙是否是窃贼*/ 25 | B=1; 26 | } 27 | if(i == 2) 28 | { 29 | B=0; /*甲乙均不是窃贼,测试丙是否是窃贼*/ 30 | C=1; 31 | } 32 | if(i == 3) 33 | { 34 | C=0; /*甲乙丙都不是窃贼,测试丁是否是窃贼*/ 35 | D=1; 36 | } 37 | } 38 | /*输出结果*/ 39 | printf("判断结果:\n"); 40 | if(i == 1) 41 | printf("甲是窃贼\n"); 42 | if(i == 2) 43 | printf("乙是窃贼\n"); 44 | if(i == 3) 45 | printf("丙是窃贼\n"); 46 | if(i == 4) 47 | printf("丁是窃贼\n"); 48 | 49 | return 0; 50 | } 51 | 52 | //运行结果: 53 | 54 | //判断结果: 55 | //乙是窃贼 56 | -------------------------------------------------------------------------------- /经典项目/谜语博士的难题.c: -------------------------------------------------------------------------------- 1 | /** 2 | 诚实族和说谎族是来自两个岛屿的不同民族,已知诚实族的人永远说真话,而说谎族的人永远说假话。 3 | 4 | 一天,谜语博士遇到3个人,知道他们可能是来自诚实族或说谎族的。为了调查这3个人到底来自哪个族,博士分别问了他们问题,下面是他们的对话: 5 | 博士问:“你们是什么族的? ” 6 | 第1个人回答说:“我们之中有2个来自诚实族。” 7 | 第2个人说:“不要胡说,我们3个人中只有一个是来自诚实族的。” 8 | 第3个人接着第2个人的话说:“对,确实只有一个是诚实族的。” 9 | 10 | 请根据他们的回答编程判断出他们分别是来自哪个族的。 11 | */ 12 | 13 | #include 14 | int main() 15 | { 16 | int A, B, C; 17 | { 18 | for(A=0; A<=1; A++) 19 | for(B=0; B<=1; B++) 20 | for(C=0; C<=1; C++) 21 | if( (A && A+B+C==2 || !A && A+B+C!=2) && 22 | (B && A+B+C==1 || !B && A+B+C!=1) && 23 | (C && A+B+C==1 || !C && A+B+C!=1) ) 24 | { 25 | printf("第一个人来自%s\n",A?"诚实族":"说谎族"); 26 | printf("第二个人来自%s\n",B?"诚实族":"说谎族"); 27 | printf("第三个人来自%s\n",C?"诚实族":"说谎族"); 28 | } 29 | } 30 | return 0; 31 | } 32 | 33 | 34 | //运行结果: 35 | 36 | //第一个人来自说谎族 37 | //第二个人来自说谎族 38 | //第三个人来自说谎族 39 | -------------------------------------------------------------------------------- /经典项目/输入一行数据并统计其长度.c: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /经典项目/输出2的N次幂.c: -------------------------------------------------------------------------------- 1 | //输出 2 的 N 次幂:1, 2, 4, 8, .. 一直到 2^N。 2 | 3 | #include 4 | #define N 16 5 | 6 | int main(void) { 7 | int n; // 记录当前指数 8 | int val = 1; // 保存 2^n 的结果 9 | 10 | printf("\t n \t 2^n\n"); 11 | printf("\t================\n"); 12 | for (n=0; n<=N; n++) { 13 | printf("\t%3d \t %6d\n", n, val); 14 | val = 2*val; 15 | } 16 | return 0; 17 | } 18 | 19 | 20 | //输出结果: 21 | // n 2^n 22 | //================ 23 | // 0 1 24 | // 1 2 25 | // 2 4 26 | // 3 8 27 | // 4 16 28 | // 5 32 29 | // 6 64 30 | // 7 128 31 | // 8 256 32 | // 9 512 33 | // 10 1024 34 | // 11 2048 35 | // 12 4096 36 | // 13 8192 37 | // 14 16384 38 | // 15 32768 39 | // 16 65536 40 | -------------------------------------------------------------------------------- /经典项目/输出菱形.c: -------------------------------------------------------------------------------- 1 | //设菱形的总行数为line,总列数为column,当前行为i,当前列为j。上半部分与下半部分的规律不一样,应该分开讨论。 2 | 3 | //我们着眼于星号(*),思考什么条件下输出星号,总结出如下的规律。 4 | 5 | //1) 对于上半部分(包括中间一行),当前行与当前列满足如下关系输出星号: 6 | //j>=(column+1)/2-(i-1) (column+1)/2-(i-1)为第i行最左边的星号 7 | //j<=(column+1)/2+(i-1) (column+1)/2+(i-1)为第i行最右边的星号 8 | 9 | //2) 对于下半部分,当前行与当前列满足如下关系输出星号: 10 | //j>=(column+1)/2-(line-i) (column+1)/2-(line-i)为第i行最左边的星号 11 | //j<=(column+1)/2+(line-i) (column+1)/2+(line-i)为第i行最右边的星号 12 | 13 | //不满足上述条件,则输出空格。 14 | 15 | 16 | #include 17 | #include 18 | 19 | int main(){ 20 | int line; // 菱形总行数 21 | int column; // 菱形总列数 22 | int i; // 当前行 23 | int j; // 当前列 24 | 25 | printf("请输入菱形的行数(奇数):"); 26 | scanf("%d", &line); 27 | if(line%2==0){ // 判断是否是奇数 28 | printf("必须输入奇数!\n"); 29 | exit(1); 30 | } 31 | column = line; // 总行数和总列数相同 32 | 33 | for(i=1; i<=line; i++){ // 遍历所有行 34 | if(i<(line+1)/2+1){ // 上半部分(包括中间一行) 35 | for(j=1; j<=column; j++){ // 遍历上半部分的所有列 36 | if( (column+1)/2-(i-1)<=j && j<=(column+1)/2+(i-1) ){ 37 | printf("*"); 38 | }else{ 39 | printf(" "); 40 | } 41 | } 42 | }else{ // 下半部分 43 | for(j=1; j<=column; j++){ // 遍历下半部分的所有列 44 | if( (column+1)/2-(line-i)<=j && j<=(column+1)/2+(line-i) ){ 45 | printf("*"); 46 | }else{ 47 | printf(" "); 48 | } 49 | } 50 | } 51 | printf("\n"); 52 | } 53 | 54 | return 0; 55 | } 56 | 57 | 58 | 59 | //运行结果: 60 | //请输入菱形的行数(奇数):11 61 | // * 62 | // *** 63 | // ***** 64 | // ******* 65 | // ********* 66 | //*********** 67 | // ********* 68 | // ******* 69 | // ***** 70 | // *** 71 | // * 72 | -------------------------------------------------------------------------------- /经典项目/递归解决分鱼问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | A、B、C、D、E这5个人合伙夜间捕鱼,凌晨时都已经疲惫不堪,于是各自在河边的树丛中找地方睡着了。 3 | 第二天日上三竿时,A第一个醒来,他将鱼平分为5份,把多余的一条扔回河中,然后拿着自己的一份回家去了; 4 | B第二个醒来,但不知道A已经拿走了一份鱼,于是他将剩下的鱼平分为5份,扔掉多余的一条,然后只拿走了自 5 | 己的一份;接着C、D、E依次醒来,也都按同样的办法分鱼。问这5人至少合伙捕到多少条鱼?每个人醒来后所看 6 | 到的鱼是多少条? 7 | */ 8 | 9 | #include 10 | /*分鱼递归函数*/ 11 | int fish(int n, int x) 12 | { 13 | if((x-1)%5 == 0) 14 | { 15 | if(n==1) 16 | return 1; /*递归出口*/ 17 | else 18 | return fish(n-1, (x-1)/5*4); /*递归调用*/ 19 | } 20 | return 0; /*x不是符合题意的解,返回0*/ 21 | } 22 | int main() 23 | { 24 | int fish[6], i; 25 | fish[5]=6; 26 | while(1) 27 | { 28 | for(i=4; i>0; i--) 29 | { 30 | if(fish[i+1]%4!=0) 31 | break; 32 | fish[i]=fish[i+1]*5/4+1; 33 | if(fish[i]%5!=1) 34 | break; 35 | } 36 | if(i == 0) 37 | break; 38 | fish[5]+=5; 39 | } 40 | for(i=1; i<=5; i++) 41 | printf("fish[%d]=%d\n", i, fish[i]); 42 | return 0; 43 | } 44 | 45 | //运行结果 46 | 47 | //fish[1]=3121 48 | //fish[2]=2496 49 | //fish[3]=1996 50 | //fish[4]=1596 51 | //fish[5]=1276 52 | -------------------------------------------------------------------------------- /经典项目/递归解决年龄问题.c: -------------------------------------------------------------------------------- 1 | /** 2 | 有5个人坐在一起,问第5个人多少岁,他说比第4个人大2岁。问第4个人多少岁,他说比第3个人大2岁。 3 | 问第3人多少岁,他说比第2个人大2岁。问第2个人多少岁,他说比第1个人大2岁。最后问第1个人,他 4 | 说他是10岁。编写程序,当输入第几个人时求出其对应的年龄。 5 | */ 6 | 7 | #include 8 | int age(int n) 9 | { 10 | int x; 11 | if(n == 1) 12 | x=10; 13 | else 14 | x=age(n-1)+2; 15 | return x; 16 | } 17 | int main() 18 | { 19 | int n; 20 | printf("请输入n值:"); 21 | scanf("%d", &n); 22 | printf("第%d个人的年龄为%d\n", n, age(n)); 23 | return 0; 24 | } 25 | 26 | //运行结果 27 | 28 | //请输入n值:5 29 | //第5个人的年龄为18 30 | -------------------------------------------------------------------------------- /经典项目/邮票组合.c: -------------------------------------------------------------------------------- 1 | /** 2 | 我们寄信都要贴邮票,在邮局有一些小面值的邮票,通过这些小面值邮票中的一张或几张的组合,可以满足不同邮件的不同邮资。 3 | 现在,邮局有4种不同面值的邮票。在每个信封上最多能贴5张邮票,面值可以相同也可以不同,要求编程求出用这4种面值所能组 4 | 成的邮资的最大值。 5 | */ 6 | 7 | #include 8 | int main() 9 | { 10 | int a, b, c, d, i, j, k, l; 11 | static int s[1000]; /*邮资*/ 12 | scanf("%d %d %d %d", &a, &b, &c, &d); /*输入四种面值邮票*/ 13 | for(i=0; i<=5; i++) /*循环变量i用于控制a分面值邮票的张数,最多5张*/ 14 | for(j=0; i+j<=5; j++) /*循环变量j用于控制b分面值邮票的张数,a分邮票+b分邮票最多5张*/ 15 | for(k=0; k+i+j<=5; k++) /*循环变量k用于控制c分面值邮票的张数,a分邮票+b分邮票+c分邮票最多5张*/ 16 | for(l=0; k+i+j+l<=5; l++) /*循环变量l用于控制d分面值邮票的张数,a分邮票+b分邮票+c分邮票+d分邮票最多5张*/ 17 | if( a*i+b*j+c*k+d*l ) 18 | s[a*i+b*j+c*k+d*l]++; 19 | for(i=1; i<=1000; i++) 20 | if( !s[i] ) 21 | break; 22 | printf("The max is %d.\n", --i); 23 | return 0; 24 | } 25 | 26 | //运行结果: 27 | 28 | //1 3 5 10 29 | //The max is 36.↙︎ 30 | -------------------------------------------------------------------------------- /经典项目/马克思手稿中的数学题.c: -------------------------------------------------------------------------------- 1 | //马克思手稿中有一道趣味数学问题:有30个人,其中有男人、女人和小孩,他们在同一家饭馆吃饭,总共花了50先令。 2 | //已知每个男人吃饭需要花3先令,每个女人吃饭需要花2先令,每个小孩吃饭需要花1先令,请编程求出男人、女人和小孩各有几人。 3 | 4 | #include 5 | int main() 6 | { 7 | int x, y, z, number=0; 8 | printf(" Men Women Children\n"); 9 | for( x=0; x<=10; x++ ) 10 | { 11 | y = 20 - 2 * x; 12 | z = 30 - x - y; 13 | if(3*x+2*y+z == 50) 14 | printf("%2d:%4d%5d%6d\n", ++number, x, y, z); 15 | } 16 | return 0; 17 | } 18 | 19 | 20 | //运行结果: 21 | // Men Women Children 22 | // 1: 0 20 10 23 | // 2: 1 18 11 24 | // 3: 2 16 12 25 | // 4: 3 14 13 26 | // 5: 4 12 14 27 | // 6: 5 10 15 28 | // 7: 6 8 16 29 | // 8: 7 6 17 30 | // 9: 8 4 18 31 | //10: 9 2 19 32 | //11: 10 0 20 33 | -------------------------------------------------------------------------------- /经典项目/验证哥德巴赫猜想.c: -------------------------------------------------------------------------------- 1 | //2000以内的不小于4的正偶数都能够分解为两个素数之和(即验证歌德巴赫猜想对2000以内的正偶数成立)。 2 | 3 | #include 4 | #include 5 | int fun(int n) 6 | { 7 | int i; 8 | if(n==2) 9 | return 1; /*n是2,返回1*/ 10 | if(n%2==0) 11 | return 0; /*n是偶数,不是素数,返回0*/ 12 | for(i=3; i<=sqrt(n); i+=2) 13 | if(n%i==0) 14 | return 0; /*n是奇数,不是素数,返回0*/ 15 | return 1; /*n是除2以外的素数返回1*/ 16 | } 17 | int main() 18 | { 19 | int n, i, ok; 20 | while(scanf("%d",&n)!=EOF) 21 | { 22 | ok=0; /*进入循环前先置标志位*/ 23 | for(i=2; i<=n/2; i++) 24 | { 25 | if( fun(i) ) 26 | if( fun(n-i) ) 27 | { 28 | printf("%d %d\n", i, n-i); /*i和n-i都是素数,则打印*/ 29 | ok=1; 30 | } 31 | if(i!=2) 32 | i++; 33 | if(ok) 34 | break; /*已打印出所需要的输出结果,跳出循环*/ 35 | } 36 | } 37 | return 0; 38 | } 39 | 40 | //运行结果: 41 | 42 | //20↙︎ 43 | //3 17 44 | -------------------------------------------------------------------------------- /经典项目/魔方阵.c: -------------------------------------------------------------------------------- 1 | /** 2 | 编写程序,实现如下表所示的5-魔方阵。 3 | 4 | 17 24 1 8 15 5 | 23 5 7 14 16 6 | 4 6 13 20 22 7 | 10 12 19 21 3 8 | 11 18 25 2 9 9 | 10 | 5-魔方阵 11 | */ 12 | 13 | 14 | #include 15 | #include 16 | 17 | int array(int n) 18 | { 19 | int i, j, no, num, max; 20 | int *mtrx; 21 | if(n%2 == 0) /*n是偶数,则加1使其变为奇数*/ 22 | { 23 | n=n+1; 24 | } 25 | max=n*n; 26 | mtrx=(int *)malloc(max+max); /*为魔方阵分配内存*/ 27 | mtrx[n/2]=1; /* 将1存入数组*/ 28 | i=0; /*自然数1所在行*/ 29 | j=n/2; /*自然数1所在列*/ 30 | /*从2开始确定每个数的存放位置*/ 31 | for(num=2; num<=max; num++) 32 | { 33 | i=i-1; 34 | j=j+1; 35 | if((num-1)%n == 0) /*当前数是n的倍数*/ 36 | { 37 | i=i+2; 38 | j=j-1; 39 | } 40 | if(i<0) /*当前数在第0行*/ 41 | { 42 | i=n-1; 43 | } 44 | if(j>n-1) /*当前数在最后一列,即n-1列*/ 45 | { 46 | j=0; 47 | } 48 | no=i*n+j; /*找到当前数在数组中的存放位置*/ 49 | mtrx[no]=num; 50 | } 51 | /*打印生成的魔方阵*/ 52 | printf("生成的%d-魔方阵为:",n); 53 | no=0; 54 | for(i=0; i 13 | int main() 14 | { 15 | int a, b, c, d, e; /*0表示黑色,1表示白色*/ 16 | for(a=0; a<=1; a++) /*穷举五个人额头帖纸颜色的全部可能*/ 17 | for(b=0; b<=1; b++) 18 | for(c=0; c<=1; c++) 19 | for(d=0; d<=1; d++) 20 | for(e=0; e<=1; e++) 21 | if( (a&&b+c+d+e==3 || !a&&b+c+d+e!=3) && 22 | (b&&a+c+d+e==0 || !b&&a+c+d+e!=0) && 23 | (c&&a+b+d+e==1 || !c&&a+b+d+e!=1) && 24 | (d&&a+b+c+e==4 || !d&&a+b+c+e!=4) 25 | ) 26 | { 27 | printf("A额头上的贴纸是%s色的.\n",a?"白":"黑"); 28 | printf("B额头上的贴纸是%s色的.\n",b?"白":"黑"); 29 | printf("C额头上的贴纸是%s色的.\n",c?"白":"黑"); 30 | printf("D额头上的贴纸是%s色的.\n",d?"白":"黑"); 31 | printf("E额头上的贴纸是%s色的.\n",e?"白":"黑"); 32 | } 33 | return 0; 34 | } 35 | 36 | //运行结果: 37 | 38 | //A额头上的贴纸是黑色的. 39 | //B额头上的贴纸是黑色的. 40 | //C额头上的贴纸是白色的. 41 | //D额头上的贴纸是黑色的. 42 | //E额头上的贴纸是白色的. 43 | -------------------------------------------------------------------------------- /老鼠走迷宫1/老鼠走迷官(1).c: -------------------------------------------------------------------------------- 1 | /* 2 | 老鼠走迷官(一) 3 | 说明老鼠走迷宫是递回求解的基本题型,我们在二维阵列中使用2表示迷宫墙壁,使用1来表 4 | 示老鼠的行走路径,试以程式求出由入口至出口的路径。 5 | 解法老鼠的走法有上、左、下、右四个方向,在每前进一格之后就选一个方向前进,无法前 6 | 进时退回选择下一个可前进方向,如此在阵列中依序测试四个方向,直到走到出口为止,这是 7 | 递回的基本题,请直接看程式应就可以理解。 8 | */ 9 | #include 10 | #include 11 | int visit(int, int); 12 | int maze[7][7] = {{2, 2, 2, 2, 2, 2, 2}, 13 | {2, 0, 0, 0, 0, 0, 2}, 14 | {2, 0, 2, 0, 2, 0, 2}, 15 | {2, 0, 0, 2, 0, 2, 2}, 16 | {2, 2, 0, 2, 0, 2, 2}, 17 | {2, 0, 0, 0, 0, 0, 2}, 18 | {2, 2, 2, 2, 2, 2, 2}}; 19 | int startI = 1, startJ = 1; // 入口 20 | int endI = 5, endJ = 5; // 出口 21 | int success = 0; 22 | int main(void) { 23 | int i, j; 24 | printf("显示迷宫:\n"); 25 | for(i = 0; i < 7; i++) { 26 | for(j = 0; j < 7; j++) 27 | if(maze[i][j] == 2) 28 | printf("█"); 29 | else 30 | printf(" "); 31 | printf("\n"); 32 | } 33 | if(visit(startI, startJ) == 0) 34 | printf("\n没有找到出口!\n"); 35 | else { 36 | printf("\n显示路径:\n"); 37 | for(i = 0; i < 7; i++) { 38 | for(j = 0; j < 7; j++) { 39 | if(maze[i][j] == 2) 40 | printf("█"); 41 | else if(maze[i][j] == 1) 42 | printf("◇"); 43 | else 44 | printf(" "); 45 | } 46 | printf("\n"); 47 | } 48 | } 49 | return 0; 50 | } 51 | int visit(int i, int j) { 52 | maze[i][j] = 1; 53 | if(i == endI && j == endJ) 54 | success = 1; 55 | if(success != 1 && maze[i][j+1] == 0) visit(i, j+1); 56 | if(success != 1 && maze[i+1][j] == 0) visit(i+1, j); 57 | if(success != 1 && maze[i][j-1] == 0) visit(i, j-1); 58 | if(success != 1 && maze[i-1][j] == 0) visit(i-1, j); 59 | if(success != 1) 60 | maze[i][j] = 0; 61 | return success; 62 | } -------------------------------------------------------------------------------- /老鼠走迷宫2/老鼠走迷官(2).c: -------------------------------------------------------------------------------- 1 | /* 2 | 老鼠走迷官(二) 3 | 说明由于迷宫的设计,老鼠走迷宫的入口至出口路径可能不只一条,如何求出所有的路径呢? 4 | 解法求所有路径看起来复杂但其实更简单,只要在老鼠走至出口时显示经过的路径,然后退 5 | 回上一格重新选择下一个位置继续递回就可以了,比求出单一路径还简单,我们的程式只要作 6 | 一点修改就可以了。 7 | */ 8 | #include 9 | #include 10 | void visit(int, int); 11 | int maze[9][9] = {{2, 2, 2, 2, 2, 2, 2, 2, 2}, 12 | {2, 0, 0, 0, 0, 0, 0, 0, 2}, 13 | {2, 0, 2, 2, 0, 2, 2, 0, 2}, 14 | {2, 0, 2, 0, 0, 2, 0, 0, 2}, 15 | {2, 0, 2, 0, 2, 0, 2, 0, 2}, 16 | {2, 0, 0, 0, 0, 0, 2, 0, 2}, 17 | {2, 2, 0, 2, 2, 0, 2, 2, 2}, 18 | {2, 0, 0, 0, 0, 0, 0, 0, 2}, 19 | {2, 2, 2, 2, 2, 2, 2, 2, 2}}; 20 | int startI = 1, startJ = 1; // 入口 21 | int endI = 7, endJ = 7; // 出口 22 | int main(void) { 23 | int i, j; 24 | printf("显示迷宫:\n"); 25 | for(i = 0; i < 7; i++) { 26 | for(j = 0; j < 7; j++) 27 | if(maze[i][j] == 2) 28 | printf("█"); 29 | else 30 | printf(" "); 31 | printf("\n"); 32 | } 33 | visit(startI, startJ); 34 | return 0; 35 | } 36 | void visit(int i, int j) { 37 | int m, n; 38 | maze[i][j] = 1; 39 | if(i == endI && j == endJ) { 40 | printf("\n显示路径:\n"); 41 | for(m = 0; m < 9; m++) { 42 | for(n = 0; n < 9; n++) 43 | if(maze[m][n] == 2) 44 | printf("█"); 45 | else if(maze[m][n] == 1) 46 | printf("◇"); 47 | else 48 | printf(" "); 49 | printf("\n"); 50 | } 51 | } 52 | if(maze[i][j+1] == 0) visit(i, j+1); 53 | if(maze[i+1][j] == 0) visit(i+1, j); 54 | if(maze[i][j-1] == 0) visit(i, j-1); 55 | if(maze[i-1][j] == 0) visit(i-1, j); 56 | maze[i][j] = 0; 57 | } -------------------------------------------------------------------------------- /背包问题/Knapsack Problem.c: -------------------------------------------------------------------------------- 1 | /* 2 | 背包问题(Knapsack Problem) 3 | */ 4 | 5 | #include 6 | #include 7 | #define LIMIT 8 8 | #define N 5 9 | #define MIN 1 10 | struct body { 11 | char name[20]; 12 | int size; 13 | int price; 14 | }; 15 | typedef struct body object; 16 | int main(void) { 17 | int item[LIMIT+1] = {0}; 18 | int value[LIMIT+1] = {0}; 19 | int newvalue, i, s, p; 20 | object a[] = {{"李子", 4, 4500}, 21 | {"苹果", 5, 5700}, 22 | {"橘子", 2, 2250}, 23 | {"草莓", 1, 1100}, 24 | {"甜瓜", 6, 6700}}; 25 | for(i = 0; i < N; i++) { 26 | for(s = a[i].size; s <= LIMIT; s++) { 27 | p = s - a[i].size; 28 | newvalue = value[p] + a[i].price; 29 | if(newvalue > value[s]) { 30 | value[s] = newvalue; 31 | item[s] = i; 32 | } 33 | } 34 | } 35 | printf("物品\t价格\n"); 36 | for(i = LIMIT; i >= MIN; i = i - a[item[i]].size) { 37 | printf("%s\t%d\n", 38 | a[item[i]].name, a[item[i]].price); 39 | } 40 | printf("合计\t%d\n", value[LIMIT]); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /视频讲解游戏/太空大战/SpaceGame.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/视频讲解游戏/太空大战/SpaceGame.rar -------------------------------------------------------------------------------- /视频讲解游戏/奇怪大冒险/Adventure.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/视频讲解游戏/奇怪大冒险/Adventure.rar -------------------------------------------------------------------------------- /视频讲解游戏/气球塔防/BalloonDefense.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/视频讲解游戏/气球塔防/BalloonDefense.rar -------------------------------------------------------------------------------- /视频讲解游戏/火柴人试炼之地/Matchman.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/视频讲解游戏/火柴人试炼之地/Matchman.rar -------------------------------------------------------------------------------- /视频讲解游戏/雷霆战机/ThunderFighter.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/视频讲解游戏/雷霆战机/ThunderFighter.rar -------------------------------------------------------------------------------- /计数排序算法/CountSort.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/计数排序算法/CountSort.c -------------------------------------------------------------------------------- /贪心算法/greedy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 贪心算法 3 | */ 4 | #include 5 | void schedule(int m,int n,int *t){ 6 | 7 | int i,j,k,max=0; 8 | int d[100],s[100][100],count[100]; 9 | for(i=0;id[j]){ 27 | min=d[j]; 28 | k=j; 29 | } 30 | } 31 | s[k][count[k]]=i; 32 | count[k]=count[k]+1; 33 | d[k]=d[k]+t[i]; 34 | } 35 | 36 | for(i=0;i 7 | #include 8 | #define N 20 9 | int main(void) { 10 | int Fib[N] = {0}; 11 | int i; 12 | Fib[0] = 0; 13 | Fib[1] = 1; 14 | for(i = 2; i < N; i++) 15 | Fib[i] = Fib[i-1] + Fib[i-2]; 16 | for(i = 0; i < N; i++) 17 | printf("%d ", Fib[i]); 18 | printf("\n"); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /资料/README.md: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /资料/数据结构1800题(含详解答案).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0voice/algorithm-structure/727e70b0f0238f9092e4d3fc9d24d6d476c2a60d/资料/数据结构1800题(含详解答案).pdf -------------------------------------------------------------------------------- /迭代加深搜索/迭代加深搜索.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool Quick_Read(int &N) { 5 | N = 0; 6 | int op = 1; 7 | char c = getchar(); 8 | while(c < '0' || c > '9') { 9 | if(c == '-') 10 | op = -1; 11 | c = getchar(); 12 | } 13 | while(c >= '0' && c <= '9') { 14 | N = (N << 1) + (N << 3) + (c ^ 48); 15 | c = getchar(); 16 | } 17 | N *= op; 18 | return N != 0; 19 | } 20 | void Quick_Write(int N) { 21 | if(N < 0) { 22 | putchar('-'); 23 | N = -N; 24 | } 25 | if(N >= 10) 26 | Quick_Write(N / 10); 27 | putchar(N % 10 + 48); 28 | } 29 | const int MAXN = 1e5 + 5; 30 | int ans[MAXN]; 31 | int limit; 32 | bool flag; 33 | int n; 34 | void Id_Dfs(int nowdepth) { 35 | if(nowdepth > limit || flag)//达到层数不在恋战或找到答案,直接跳出 36 | return; 37 | if(ans[nowdepth] == n) {//满足题意 38 | flag = true; 39 | return; 40 | } 41 | for(int i = nowdepth; i >= 1; i--) { 42 | for(int j = nowdepth; j >= i; j--) {//两两搭配,且答案越大越容易找到解,故而到着找 43 | if(ans[i] + ans[j] <= n && ans[i] + ans[j] > ans[nowdepth]) {//满足题意1,2两点的搜索 44 | int now;//找到下一项 45 | ans[nowdepth + 1] = now = ans[i] + ans[j]; 46 | for(int k = nowdepth + 2; k <= limit; k++) 47 | //从nowdepth + 1这一项开始,后面最大时也就是now不停扩大2倍,若最大都达不到n,舍去不求 48 | now <<= 1; 49 | if(now < n) 50 | continue; 51 | Id_Dfs(nowdepth + 1);//搜索下一层 52 | if(flag)//找到答案 53 | return; 54 | } 55 | } 56 | } 57 | } 58 | void Work() { 59 | for(; !flag; limit++)//直到找到答案时停止搜索 60 | Id_Dfs(1); 61 | for(int i = 1; i < limit; i++) {//输出 62 | Quick_Write(ans[i]); 63 | putchar(' '); 64 | } 65 | putchar('\n'); 66 | } 67 | void Init() { 68 | limit = 1; 69 | int test = 1; 70 | while(test < n) {//找到最小层数 71 | test <<= 1; 72 | limit++; 73 | } 74 | ans[1] = 1; 75 | flag = false; 76 | } 77 | int main() { 78 | while(Quick_Read(n)) {//多组输入输出,到0为止 79 | Init(); 80 | Work(); 81 | } 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /选择排序算法/README.md: -------------------------------------------------------------------------------- 1 | # SelectSort 2 | "选择排序" 3 | -------------------------------------------------------------------------------- /选择排序算法/selectsort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 选择排序算法 3 | * create by JackChen 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | 10 | void selectsort(int arr[],int nlenght) 11 | { 12 | 13 | int i,j; 14 | int min; 15 | for(i = 0;i 4 | const int L = 7; 5 | int RecurMatrixChain(int i, int j, int **s, int *p); 6 | void Traceback(int i, int j, int **s); 7 | 8 | int main() 9 | { 10 | int p[] = { 30, 35, 15, 5, 10, 20, 25 }; 11 | int **s = (int**)malloc(L*sizeof(int*)); 12 | for (int i = 0; i < L; i++){ 13 | s[i] = (int*)malloc(L*sizeof(int)); 14 | } 15 | printf("矩阵的最少计算次数为:%d\n", RecurMatrixChain(1, 6, s, p)); 16 | printf("矩阵最优计算次序为:\n"); 17 | Traceback(1, 6, s); 18 | return 0; 19 | } 20 | 21 | int RecurMatrixChain(int i, int j, int **s, int *p) 22 | { 23 | if (i == j) return 0; 24 | int u = RecurMatrixChain(i, i, s, p) + RecurMatrixChain(i + 1, j, s, p) + p[i - 1] * p[i] * p[j]; 25 | s[i][j] = i; 26 | for (int k = i + 1; k 2 | #include 3 | typedef struct QNode{ 4 | int data; 5 | struct QNode * next; 6 | }QNode; 7 | QNode * initQueue(){ 8 | QNode * queue=(QNode*)malloc(sizeof(QNode)); 9 | queue->next=NULL; 10 | return queue; 11 | } 12 | QNode* enQueue(QNode * rear,int data){ 13 | QNode * enElem=(QNode*)malloc(sizeof(QNode)); 14 | enElem->data=data; 15 | enElem->next=NULL; 16 | //使用尾插法向链队列中添加数据元素 17 | rear->next=enElem; 18 | rear=enElem; 19 | return rear; 20 | } 21 | QNode* DeQueue(QNode * top,QNode * rear){ 22 | if (top->next==NULL) { 23 | printf("\n队列为空"); 24 | return rear; 25 | } 26 | QNode * p=top->next; 27 | printf("%d ",p->data); 28 | top->next=p->next; 29 | if (rear==p) { 30 | rear=top; 31 | } 32 | free(p); 33 | return rear; 34 | } 35 | int main() { 36 | QNode * queue,*top,*rear; 37 | queue=top=rear=initQueue();//创建头结点 38 | //向链队列中添加结点,使用尾插法添加的同时,队尾指针需要指向链表的最后一个元素 39 | rear=enQueue(rear, 1); 40 | rear=enQueue(rear, 2); 41 | rear=enQueue(rear, 3); 42 | rear=enQueue(rear, 4); 43 | //入队完成,所有数据元素开始出队列 44 | rear=DeQueue(top, rear); 45 | rear=DeQueue(top, rear); 46 | rear=DeQueue(top, rear); 47 | rear=DeQueue(top, rear); 48 | rear=DeQueue(top, rear); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /阿姆斯壮数/阿姆斯壮数.c: -------------------------------------------------------------------------------- 1 | /* 2 | 阿姆斯壮数 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | int main(void) { 9 | int a, b, c; 10 | int input; 11 | printf("寻找Armstrong数:\n"); 12 | for(input = 100; input <= 999; input++) { 13 | a = input / 100; 14 | b = (input % 100) / 10; 15 | c = input % 10; 16 | if(a*a*a + b*b*b + c*c*c == input) 17 | printf("%d ", input); 18 | } 19 | printf("\n"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /顺序查找/顺序查找.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define keyType int 4 | typedef struct { 5 | keyType key;//查找表中每个数据元素的值 6 | //如果需要,还可以添加其他属性 7 | }ElemType; 8 | 9 | typedef struct{ 10 | ElemType *elem;//存放查找表中数据元素的数组 11 | int length;//记录查找表中数据的总数量 12 | }SSTable; 13 | //创建查找表 14 | void Create(SSTable **st,int length){ 15 | (*st)=(SSTable*)malloc(sizeof(SSTable)); 16 | (*st)->length=length; 17 | (*st)->elem =(ElemType*)malloc((length+1)*sizeof(ElemType)); 18 | printf("输入表中的数据元素:\n"); 19 | //根据查找表中数据元素的总长度,在存储时,从数组下标为 1 的空间开始存储数据 20 | for (int i=1; i<=length; i++) { 21 | scanf("%d",&((*st)->elem[i].key)); 22 | } 23 | } 24 | //查找表查找的功能函数,其中key为关键字 25 | int Search_seq(SSTable *st,keyType key){ 26 | st->elem[0].key=key;//将关键字作为一个数据元素存放到查找表的第一个位置,起监视哨的作用 27 | int i=st->length; 28 | //从查找表的最后一个数据元素依次遍历,一直遍历到数组下标为0 29 | while (st->elem[i].key!=key) { 30 | i--; 31 | } 32 | //如果 i=0,说明查找失败;反之,返回的是含有关键字key的数据元素在查找表中的位置 33 | return i; 34 | } 35 | int main() { 36 | SSTable *st; 37 | Create(&st, 6); 38 | getchar(); 39 | printf("请输入查找数据的关键字:\n"); 40 | int key; 41 | scanf("%d",&key); 42 | int location=Search_seq(st, key); 43 | if (location==0) { 44 | printf("查找失败"); 45 | }else{ 46 | printf("数据在查找表中的位置为:%d",location); 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /顺序队列/顺序队列.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int enQueue(int *a,int rear,int data){ 4 | a[rear]=data; 5 | rear++; 6 | return rear; 7 | } 8 | 9 | void deQueue(int *a,int front,int rear){ 10 | //如果 front==rear,表示队列为空 11 | while (front!=rear) { 12 | printf("出队元素:%d\n",a[front]); 13 | front++; 14 | } 15 | } 16 | 17 | int main() { 18 | int a[100]; 19 | int front,rear; 20 | //设置队头指针和队尾指针,当队列中没有元素时,队头和队尾指向同一块地址 21 | front=rear=0; 22 | //入队 23 | rear=enQueue(a, rear, 1); 24 | rear=enQueue(a, rear, 2); 25 | rear=enQueue(a, rear, 3); 26 | rear=enQueue(a, rear, 4); 27 | //出队 28 | deQueue(a, front, rear); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /魔方阵1/魔方阵(1).c: -------------------------------------------------------------------------------- 1 | /* 2 | 奇数魔方阵 3 | 说明 4 | 将1到n(为奇数)的数字排列在nxn的方阵上,且各行、各列与各对角线的和必须相同,如下所 5 | 示: 6 | 解法 7 | 填魔术方阵的方法以奇数最为简单,第一个数字放在第一行第一列的正中央,然后向右(左)上 8 | 填,如果右(左)上已有数字,则向下填,如下图所示: 9 | 一般程式语言的阵列索引多由0开始,为了计算方便,我们利用索引1到n的部份,而在计算是向 10 | 右(左)上或向下时,我们可以将索引值除以n值,如果得到余数为1就向下,否则就往右(左)上, 11 | 原理很简单,看看是不是已经在同一列上绕一圈就对了。 12 | */ 13 | 14 | #include 15 | #include 16 | #define N 5 17 | int main(void) { 18 | int i, j, key; 19 | int square[N+1][N+1] = {0}; 20 | i = 0; 21 | j = (N+1) / 2; 22 | for(key = 1; key <= N*N; key++) { 23 | if((key % N) == 1) 24 | i++; 25 | else { 26 | i--; 27 | j++; 28 | } 29 | if(i == 0) 30 | i = N; 31 | if(j > N) 32 | j = 1; 33 | square[i][j] = key; 34 | } 35 | for(i = 1; i <= N; i++) { 36 | for(j = 1; j <= N; j++) 37 | printf("%2d ", square[i][j]); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /魔方阵2/魔方阵(2).c: -------------------------------------------------------------------------------- 1 | /* 2 | 4N魔方阵 3 | 说明 4 | 与奇数魔术方阵相同,在于求各行、各列与各对角线的和相等,而这次方阵的维度是4的倍 5 | 数。 6 | 解法 7 | 先来看看4X4方阵的解法: 8 | 简单的说,就是一个从左上由1依序开始填,但遇对角线不填,另一个由左上由16开始填,但只 9 | 填在对角线,再将两个合起来就是解答了;如果N大于2,则以4X4为单位画对角线: 10 | 至于对角线的位置该如何判断,有两个公式,有兴趣的可以画图印证看看,如下所示: 11 | 左上至右下:j % 4 == i % 4 12 | 右上至左下:(j % 4 + i % 4) == 1 13 | */ 14 | 15 | #include 16 | #include 17 | #define N 8 18 | int main(void) { 19 | int i, j; 20 | int square[N+1][N+1] = {0}; 21 | for(j = 1; j <= N; j++) { 22 | for(i = 1; i <= N; i++){ 23 | if(j % 4 == i % 4 || (j % 4 + i % 4) == 1) 24 | square[i][j] = (N+1-i) * N -j + 1; 25 | else 26 | square[i][j] = (i - 1) * N + j; 27 | } 28 | } 29 | for(i = 1; i <= N; i++) { 30 | for(j = 1; j <= N; j++) 31 | printf("%2d ", square[i][j]); 32 | printf("\n"); 33 | } 34 | return 0; 35 | } 36 | --------------------------------------------------------------------------------