Skip to content

Commit

Permalink
继续补充
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoMinC committed Jul 3, 2020
1 parent 46e577d commit 89375eb
Show file tree
Hide file tree
Showing 23 changed files with 1,473 additions and 0 deletions.
63 changes: 63 additions & 0 deletions 乱数排列/乱数排列.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
洗扑克牌(乱数排列)
说明
洗扑克牌的原理其实与乱数排列是相同的,都是将一组数字(例如1~N)打乱重新排列,只
不过洗扑克牌多了一个花色判断的动作而已。
解法
初学者通常会直接想到,随机产生1~N的乱数并将之存入阵列中,后来产生的乱数存入阵列
前必须先检查阵列中是否已有重复的数字,如果有这个数就不存入,再重新产生下一个数,运
气不好的话,重复的次数就会很多,程式的执行速度就很慢了,这不是一个好方法。
以1~52的乱数排列为例好了,可以将阵列先依序由1到52填入,然后使用一个回圈走访阵列,
并随机产生1~52的乱数,将产生的乱数当作索引取出阵列值,并与目前阵列走访到的值相交换,
如此就不用担心乱数重复的问题了,阵列走访完毕后,所有的数字也就重新排列了。
至于如何判断花色?这只是除法的问题而已,取商数判断花色,取余数判断数字,您可以直接
看程式比较清楚。
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 52
int main(void) {
int poker[N + 1];
int i, j, tmp, remain;
// 初始化阵列
for(i = 1; i <= N; i++)
poker[i] = i;
srand(time(0));
// 洗牌
for(i = 1; i <= N; i++) {
j = rand() % 52 + 1;
tmp = poker[i];
poker[i] = poker[j];
poker[j] = tmp;
}
for(i = 1; i <= N; i++) {
// 判断花色
switch((poker[i]-1) / 13) {
case 0:
printf("桃"); break;
case 1:
printf("心"); break;
case 2:
printf("砖"); break;
case 3:
printf("梅"); break;
}
// 扑克牌数字
remain = poker[i] % 13;
switch(remain) {
case 0:
printf("K "); break;
case 12:
printf("Q "); break;
case 11:
printf("J "); break;
default:
printf("%d ", remain); break;
}
if(i % 13 == 0)
printf("\n");
}
return 0;
}
75 changes: 75 additions & 0 deletions 二分搜寻法/二分搜寻法.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
二分搜寻法(搜寻原则的代表)
说明如果搜寻的数列已经有排序,应该尽量利用它们已排序的特性,以减少搜寻比对的次数,
这是搜寻的基本原则,二分搜寻法是这个基本原则的代表。
解法在二分搜寻法中,从数列的中间开始搜寻,如果这个数小于我们所搜寻的数,由于数列
已排序,则该数左边的数一定都小于要搜寻的对象,所以无需浪费时间在左边的数;如果搜寻
的数大于所搜寻的对象,则右边的数无需再搜寻,直接搜寻左边的数。
所以在二分搜寻法中,将数列不断的分为两个部份,每次从分割的部份中取中间数比对,例如
要搜寻92于以下的数列,首先中间数索引为(0+9)/2 = 4(索引由0开始):
[3 24 57 57 67 68 83 90 92 95]
由于67小于92,所以转搜寻右边的数列:
3 24 57 57 67 [68 83 90 92 95]
由于90小于92,再搜寻右边的数列,这次就找到所要的数了:
3 24 57 57 67 68 83 90 [92 95]
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
#define SWAP(x,y) {int t; t = x; x = y; y = t;}
void quicksort(int[], int, int);
int bisearch(int[], int);
int main(void) {
int number[MAX] = {0};
int i, find;
srand(time(NULL));
for(i = 0; i < MAX; i++) {
number[i] = rand() % 100;
}
quicksort(number, 0, MAX-1);
printf("数列:");
for(i = 0; i < MAX; i++)
printf("%d ", number[i]);
printf("\n输入寻找对象:");
scanf("%d", &find);
if((i = bisearch(number, find)) >= 0)
printf("找到数字于索引%d ", i);
else
printf("\n找不到指定数");
printf("\n");
return 0;
}
int bisearch(int number[], int find) {
int low, mid, upper;
low = 0;
upper = MAX - 1;
while(low <= upper) {
mid = (low+upper) / 2;
if(number[mid] < find)
low = mid+1;
else if(number[mid] > find)
upper = mid - 1;
else
return mid;
}
return -1;
}
void quicksort(int number[], int left, int right) {
int i, j, k, s;
if(left < right) {
s = number[(left+right)/2];
i = left - 1;
j = right + 1;
while(1) {
while(number[++i] < s) ; // 向右找
while(number[--j] > s) ; // 向左找
if(i >= j)
break;
SWAP(number[i], number[j]);
}
quicksort(number, left, i-1); // 对左边进行递回
quicksort(number, j+1, right); // 对右边进行递回
}
}
101 changes: 101 additions & 0 deletions 产生可能的集合/产生可能的集合.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
产生可能的集合
说明
给定一组数字或符号,产生所有可能的集合(包括空集合), 例如给定1 2 3,则可能的集合为:
{}、{1}、{1,2}、{1,2,3}、{1,3}、{2}、{2,3}、{3}。
解法
如果不考虑字典顺序,则有个简单的方法可以产生所有的集合,思考二进位数字加法,并注意
1出现的位置,如果每个位置都对应一个数字,则由1所对应的数字所产生的就是一个集合,例
如:
了解这个方法之后,剩下的就是如何产生二进位数?有许多方法可以使用,您可以使用unsigned
型别加上&位元运算来产生,这边则是使用阵列搜寻,首先阵列内容全为0,找第一个1,在还
没找到之前将走访过的内容变为0,而第一个找到的0则变为1,如此重复直到所有的阵列元素
都变为1为止,例如:
000 => 100 => 010 => 110 => 001 => 101 => 011 => 111
如果要产生字典顺序,例如若有4个元素,则:
{} => {1} => {1,2} => {1,2,3} => {1,2,3,4} =>
{1,2,4} =>
{1,3} => {1,3,4} =>
{1,4} =>
{2} => {2,3} => {2,3,4} =>
{2,4} =>
{3} => {3,4} =>
000 {}
001 {3}
010 {2}
011 {2,3}
100 {1}
101 {1,3}
110 {1,2}
111 {1,2,3}
{4}
简单的说,如果有n个元素要产生可能的集合,当依序产生集合时,如果最后一个元素是n,而
倒数第二个元素是m的话,例如:
{a b c d e n}
则下一个集合就是{a b c d e+1},再依序加入后续的元素。
例如有四个元素,而当产生{1 2 3 4}集合时,则下一个集合就是{1 2 3+1},也就是{1 2 4},由于
最后一个元素还是4,所以下一个集合就是{1 2+1},也就是{1 3},接下来再加入后续元素4,也
就是{1 3 4},由于又遇到元素4,所以下一个集合是{1 3+1},也就是{1 4}。
*/

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 20
int main(void) {
char digit[MAXSIZE];
int i, j;
int n;
printf("输入集合个数:");
scanf("%d", &n);
for(i = 0; i < n; i++)
digit[i] = '0';
printf("\n{}"); // 空集合
while(1) {
// 找第一个0,并将找到前所经过的元素变为0
for(i = 0; i < n && digit[i] == '1'; digit[i] = '0', i++);
if(i == n) // 找不到0
break;
else // 将第一个找到的0变为1
digit[i] = '1';
// 找第一个1,并记录对应位置
for(i = 0; i < n && digit[i] == '0'; i++);
printf("\n{%d", i+1);
for(j = i + 1; j < n; j++)
if(digit[j] == '1')
printf(",%d", j + 1);
printf("}");
}
printf("\n");
return 0;
}

//C(字典顺序)
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 20
int main(void) {
int set[MAXSIZE];
int i, n, position = 0;
printf("输入集合个数:");
scanf("%d", &n);
printf("\n{}");
set[position] = 1;
while(1) {
printf("\n{%d", set[0]); // 印第一个数
for(i = 1; i <= position; i++)
printf(",%d", set[i]);
printf("}");
if(set[position] < n) { // 递增集合个数
set[position+1] = set[position] + 1;
position++;
}
else if(position != 0) { // 如果不是第一个位置
position--; // 倒退
set[position]++; // 下一个集合尾数
}
else // 已倒退至第一个位置
break;
}
printf("\n");
return 0;
}
58 changes: 58 additions & 0 deletions 八枚银币/八枚银币.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
八枚银币
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void compare(int[], int, int, int);
void eightcoins(int[]);
int main(void) {
int coins[8] = {0};
int i;
srand(time(NULL));
for(i = 0; i < 8; i++)
coins[i] = 10;
printf("\n输入假币重量(比10大或小):");
scanf("%d", &i);
coins[rand() % 8] = i;
eightcoins(coins);
printf("\n\n列出所有钱币重量:");
for(i = 0; i < 8; i++)
printf("%d ", coins[i]);
printf("\n");
return 0;
}
void compare(int coins[], int i, int j, int k) {
if(coins[i] > coins[k])
printf("\n假币%d 较重", i+1);
else
printf("\n假币%d 较轻", j+1);
}
void eightcoins(int coins[]) {
if(coins[0]+coins[1]+coins[2] ==
coins[3]+coins[4]+coins[5]) {
if(coins[6] > coins[7])
compare(coins, 6, 7, 0);
else
compare(coins, 7, 6, 0);
}
else if(coins[0]+coins[1]+coins[2] >
coins[3]+coins[4]+coins[5]) {
if(coins[0]+coins[3] == coins[1]+coins[4])
compare(coins, 2, 5, 0);
else if(coins[0]+coins[3] > coins[1]+coins[4])
compare(coins, 0, 4, 1);
if(coins[0]+coins[3] < coins[1]+coins[4])
compare(coins, 1, 3, 0);
}
else if(coins[0]+coins[1]+coins[2] <
coins[3]+coins[4]+coins[5]) {
if(coins[0]+coins[3] == coins[1]+coins[4])
compare(coins, 5, 2, 0);
else if(coins[0]+coins[3] > coins[1]+coins[4])
compare(coins, 3, 1, 0);
if(coins[0]+coins[3] < coins[1]+coins[4])
compare(coins, 4, 0, 1);
}
}
54 changes: 54 additions & 0 deletions 八皇后/八皇后.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
八皇后
*/
#include <stdio.h>
#include <stdlib.h>
#define N 8
int column[N+1]; // 同栏是否有皇后,1表示有
int rup[2*N+1]; // 右上至左下是否有皇后
int lup[2*N+1]; // 左上至右下是否有皇后
int queen[N+1] = {0};
int num; // 解答编号
void backtrack(int); // 递回求解
int main(void) {
int i;
num = 0;
for(i = 1; i <= N; i++)
column[i] = 1;
for(i = 1; i <= 2*N; i++)
rup[i] = lup[i] = 1;
backtrack(1);
return 0;
}
void showAnswer() {
int x, y;
printf("\n解答%d\n", ++num);
for(y = 1; y <= N; y++) {
for(x = 1; x <= N; x++) {
if(queen[y] == x) {
printf(" Q");
}
else {
printf(" .");
}
}
printf("\n");
}
}
void backtrack(int i) {
int j;
if(i > N) {
showAnswer();
}
else {
for(j = 1; j <= N; j++) {
if(column[j] == 1 &&
rup[i+j] == 1 && lup[i-j+N] == 1) {
queen[i] = j;
column[j] = rup[i+j] = lup[i-j+N] = 0;
backtrack(i+1);
column[j] = rup[i+j] = lup[i-j+N] = 1;
}
}
}
}
Loading

0 comments on commit 89375eb

Please sign in to comment.