想想下面这个算法:求链表所有数据的平均值(我也没试过),不许偷懒,用递归试试哦!
递归程序员考试题目类型:1)就是链表的某些操作(比如上面的求平均值)
2)二叉树(遍历等)
例2.判断数组元素是否递增
int jidge(int a[],int n) {
if(n==1) return 1;
else
if(a[0]>a[1]) return 0;
else return jidge(a+1,n-1);
}
例3.求二叉树的高度(根据二叉树的递归性质:(左子树)根(右子树))
int depth(nodetype *root) {
if(root==NULL)
return 0;
else {
h1=depth(root->lch);
h2=depth(root->rch);
return max(h1,h2)+1;
}
}
自己想想求二叉树结点个数(与上例类似)
例4.已知中序遍历和后序遍历,求二叉树.
设一二叉树的:
中序 S:E D F B A G J H C I
^start1 ^j ^end1
后序 T:E F D B J H G I C A
^start2 ^end2
node *create(char *s,char *t, int start1,int start2,int end1,int end2)
{ if (start1>end1) return NULL; //回归条件
root=(node *)malloc(sizeof(node));
root->data=t[end2];
找到S中T[end2]的位置为 j
root->lch=create(S,T,s1,j-1,start1,j+start2-start1-1);
root->rch=create(S,T,j+1,end1,j+start2-start1,end2-1);
return root;
}
例5.组合问题
n 个数: (1,2,3,4,…n)求从中取r个数的所有组合.
设n=5,r=3;
递归思想:先固定一位 5 (从另四个数当中选二个)
5,4 (从另三个数当中选一个)
5,4,3 (从另二个数当中选零个)
即:n-2个数中取r-2个数的所有组合
…
程序:
void combire(int n,int r) {
for(k=n;k>=n+r-1;k--) {
a[r]=k;
if(r==0) 打印a数组(表示找到一个解);
else combire(n-1,r-1);
}
}
回溯法:
回溯跟递归都是程序员考试里常出现的问题,大家必须掌握!
回溯法的有关概念:
1) 解答树:叶子结点可能是解,对结点进行后序遍历.
2) 搜索与回溯
五个数中任选三个的解答树(解肯定有三层,至叶子结点):
ROOT 虚根
/ / |
1 2 3 4 5
/ | | / | / |
2 3 4 5 3 4 5 4 5 5
/| / | / | |
3 4 5 4 5 5 4 5 5 5
回溯算法实现中的技巧:栈
要搞清回溯算法,先举一个(中序遍历二叉树的非递归算法)来说明栈在非递归中所起的作用。
A 过程:push()->push()->push()->push()栈内结果:ABDE(E为叶子,结束进栈)
/ pop() ABD(E无右孩子,出栈)
B C pop() AB(D无右孩子,出栈)
/ pop() A(B有右孩子,右孩子进栈)
D F . .
/ / . .
E G H . .
/ . .
I 最后结果: EDBGFIHAC
简单算法:
…
if(r!=NULL) //树不空
{ while(r!=NULL)
{ push(s,r);
r=r->lch; //一直向左孩子前进
}
while(!empty(s)) // 栈非空,出栈
{ p=pop(s);
printf(p->data);
p=p->rch; //向右孩子前进
while(p!=NULL)
{ push(s,p);
p=p->lch; //右孩子进栈
}
}
} //这就是传说中的回溯,嘻嘻……没吓着你吧
5选3问题算法:
思想: 进栈:搜索
出栈:回溯
边建树(进栈)边遍历(出栈)
基本流程:
太复杂了,再说我不太喜欢用WORD画图(有损形象),以后再整理!
程序: n=5;r=3
……
init(s) //初始化栈
push(s,1) //根进栈
while(s.top<r-1)&&(s.data[s.top]!=n) //有孩子
push(s,s.data[s.top]+1); //孩子入栈
while(!empty(s))
{ if(s.top=r-1)
判断该"解"是否为解.
x=pop(s); //保留x,判断是否为最大值n,如果是n,则出栈
while(x==n)
x=pop(s);
push(s,x+1);
while(s.top<r-1)&&(s.data[s.top]!=n)
push(s,s.data[s.top]+1);
}
背包问题: TW=20 , w[5]={6,10,7,5,8}
解的条件:1) 该解答树的叶子结点
2) 重量最大
解答树如下: ROOT
/ | | |
6 10 7 5 8
/ | | / | / |
10 7 5 8 7 5 8 5 8 8
| | |
5 8 8
递归程序员考试题目类型:1)就是链表的某些操作(比如上面的求平均值)
2)二叉树(遍历等)
例2.判断数组元素是否递增
int jidge(int a[],int n) {
if(n==1) return 1;
else
if(a[0]>a[1]) return 0;
else return jidge(a+1,n-1);
}
例3.求二叉树的高度(根据二叉树的递归性质:(左子树)根(右子树))
int depth(nodetype *root) {
if(root==NULL)
return 0;
else {
h1=depth(root->lch);
h2=depth(root->rch);
return max(h1,h2)+1;
}
}
自己想想求二叉树结点个数(与上例类似)
例4.已知中序遍历和后序遍历,求二叉树.
设一二叉树的:
中序 S:E D F B A G J H C I
^start1 ^j ^end1
后序 T:E F D B J H G I C A
^start2 ^end2
node *create(char *s,char *t, int start1,int start2,int end1,int end2)
{ if (start1>end1) return NULL; //回归条件
root=(node *)malloc(sizeof(node));
root->data=t[end2];
找到S中T[end2]的位置为 j
root->lch=create(S,T,s1,j-1,start1,j+start2-start1-1);
root->rch=create(S,T,j+1,end1,j+start2-start1,end2-1);
return root;
}
例5.组合问题
n 个数: (1,2,3,4,…n)求从中取r个数的所有组合.
设n=5,r=3;
递归思想:先固定一位 5 (从另四个数当中选二个)
5,4 (从另三个数当中选一个)
5,4,3 (从另二个数当中选零个)
即:n-2个数中取r-2个数的所有组合
…
程序:
void combire(int n,int r) {
for(k=n;k>=n+r-1;k--) {
a[r]=k;
if(r==0) 打印a数组(表示找到一个解);
else combire(n-1,r-1);
}
}
回溯法:
回溯跟递归都是程序员考试里常出现的问题,大家必须掌握!
回溯法的有关概念:
1) 解答树:叶子结点可能是解,对结点进行后序遍历.
2) 搜索与回溯
五个数中任选三个的解答树(解肯定有三层,至叶子结点):
ROOT 虚根
/ / |
1 2 3 4 5
/ | | / | / |
2 3 4 5 3 4 5 4 5 5
/| / | / | |
3 4 5 4 5 5 4 5 5 5
回溯算法实现中的技巧:栈
要搞清回溯算法,先举一个(中序遍历二叉树的非递归算法)来说明栈在非递归中所起的作用。
A 过程:push()->push()->push()->push()栈内结果:ABDE(E为叶子,结束进栈)
/ pop() ABD(E无右孩子,出栈)
B C pop() AB(D无右孩子,出栈)
/ pop() A(B有右孩子,右孩子进栈)
D F . .
/ / . .
E G H . .
/ . .
I 最后结果: EDBGFIHAC
简单算法:
…
if(r!=NULL) //树不空
{ while(r!=NULL)
{ push(s,r);
r=r->lch; //一直向左孩子前进
}
while(!empty(s)) // 栈非空,出栈
{ p=pop(s);
printf(p->data);
p=p->rch; //向右孩子前进
while(p!=NULL)
{ push(s,p);
p=p->lch; //右孩子进栈
}
}
} //这就是传说中的回溯,嘻嘻……没吓着你吧
5选3问题算法:
思想: 进栈:搜索
出栈:回溯
边建树(进栈)边遍历(出栈)
基本流程:
太复杂了,再说我不太喜欢用WORD画图(有损形象),以后再整理!
程序: n=5;r=3
……
init(s) //初始化栈
push(s,1) //根进栈
while(s.top<r-1)&&(s.data[s.top]!=n) //有孩子
push(s,s.data[s.top]+1); //孩子入栈
while(!empty(s))
{ if(s.top=r-1)
判断该"解"是否为解.
x=pop(s); //保留x,判断是否为最大值n,如果是n,则出栈
while(x==n)
x=pop(s);
push(s,x+1);
while(s.top<r-1)&&(s.data[s.top]!=n)
push(s,s.data[s.top]+1);
}
背包问题: TW=20 , w[5]={6,10,7,5,8}
解的条件:1) 该解答树的叶子结点
2) 重量最大
解答树如下: ROOT
/ | | |
6 10 7 5 8
/ | | / | / |
10 7 5 8 7 5 8 5 8 8
| | |
5 8 8