forked from 0voice/algorithm-structure
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
1,473 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); // 对右边进行递回 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.