递归简论
递归的两个基本法则
1、 基准情形:你必须总要有某些基准的情形,他们不用递归就能求解。
2、 不断推进:对于那些需要递归求解的情形,递归调用必须总能够朝着产生基准情形的方向推进。
设计法则:假设所有的递归调用都能运行。
合成效益法则:在求解同一个问题的同一个实例时,切勿在不同的递归调用中做重复性的工作。
练习
1.1 编写一个程序解决选择问题。令k = N/2。画出表格显示你的程序对于N为不同值的运行时间。
#include <stdio.h>
#define ArrayNum 10
#define ResultNum (ArrayNum/2)
void JiangPaiXu(int* pArr, int num);
void main()
{
int array[ArrayNum] = {
9, 3, 10, 2, 25, 7, 8, 14, 17, 12 };
for (int i = 0; i < ArrayNum; i++)
{
printf("%d ", array[i]);
}
printf("\n");
// 从原始数组中取出ResultNum各元素,然后进行降排序
int ResultArray[ResultNum];
for (int i = 0; i < ResultNum; i++)
{
ResultArray[i] = array[i];
}
JiangPaiXu(ResultArray, ResultNum);
for (int i = ResultNum; i < ArrayNum; i++)
{
if (ResultArray[ResultNum - 1] < array[i])
{
ResultArray[ResultNum - 1] = array[i];
JiangPaiXu(ResultArray, ResultNum);
}
}
printf("第k/2个值 : %d \n", ResultArray[ResultNum - 1]);
}
void JiangPaiXu(int* pArr, int num)
{
int temp;
for (int i = 0; i < num -1; i++)
{
for (int j = 0; j < num - 1 - i; j++)
{
if (pArr[j] < pArr[j + 1])
{
temp = pArr[j];
pArr[j] = pArr[j + 1];
pArr[j + 1] = temp;
}
}
}
}
1.2 编写一个程序求解字谜游戏问题。【参考文献1】【参考文献2】
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DICTSIZE 4 // 字典内最大单词数
#define WORDSIZE 21 // 单词最大长度 +1
char puzzle[4][4] = {
{
't', 'h', 'i', 's'},
{
'w', 'a', 't', 's'},
{
'o', 'a', 'h', 'g'},
{
'f', 'g', 'g', 't'}
}; // 字谜
char* dict[DICTSIZE] = {
"this", "two", "fat", "that" }; // 字典
int wordExist(int x, int y, int dir, int maxChars, char* retWord);
void main()
{
char word[WORDSIZE];
for (int i = 0; i < 4; i++) // 行
{
for (int j = 0; j < 4; j++) //列
{
for (int d = 0; d < 8; d++) // 方向
{
for (int n = 1; n <= 4; n++) // 最大字符数
{
if (wordExist(i, j, d, n, word))
{
printf("%s\n", word);
break;
}
}
}
}
}
}
int wordExist(int x, int y, int dir, int maxChars, char* retWord)
{
char str[WORDSIZE];
int ct = 0;
for (int i = 0; i < maxChars; i++)
{
// 添加(x, y)处的一个字符
str[ct] = puzzle[x][y];
str[ct + 1] = '\0';
// 拿stc到字典内遍历
for (int j = 0; j < DICTSIZE; j++) // 第一次遍历时,是找一个字母的单词
{
if (strcmp(str, dict[j]) == 0)
{
strcpy(retWord, dict[j]);
return 1;
}
}
ct++;
// 确定下一个字符位姿(x,y)
switch (dir)
{
case 0: // 从左到右
y++;
break;
case 1: // 从右到左
y--;
break;
case 2:// 从上到下
x++;
break;
case 3:// 从下到到上
x--;
break;
case 4:// 从左上到右下
x++;
y++;
break;
case 5:// 从右下到左上
x--;
y--;
break;
case 6:// 从右上到左下
x--;
y++;
break;
case 7:// 从左下到右上
x++;
y--;
break;
default:
printf("Direction error.");
return 0;
}
}
return 0;
}
注:此答案中有bug,若单个字母“a”,两个字母“at”。
1.3 只使用处理I/O的PrintDigit函数,编写一个过程以输出任意实数(可以是负的)。
#include <stdio.h>
void PrintDigit(int number);
void PrintOut(int N);
void main()
{
int num = -72634;
PrintOut(num);
}
void PrintDigit(int number)
{
printf("%d ", number);
}
void PrintOut(int N)
{
if (N >= 10 || N <= -10)
PrintOut(N / 10);
PrintDigit(N -(N/10)*10);
}