**
递归
**
学习前提:
1.了解数据结构的知识
2.理解C/C++/Java等编程语言
3.理解栈的工作原理
下面进入正题😜
欢迎进入递归的世界,希望我的学习成果可以对你理解递归有一定的帮助,那样我就会很开心啦😊
神魔是递归😱?
递归是一种编程方式,利用系统栈的方式进行编程(不用自己再调用栈的包)主要来处理一些顺序性问题,如递归上升解决问题,和递归下降解决问题。
*递归上升:先递归到尾部,然后再通过递归返回来求解问题
*递归下降:先从后面往前递归,再从前到后返回来求解问题
学习后的要求
理解递归的原理、过程,求解递归问题的共性
掌握递归函数的编程技巧
应用递归函数求解现实问题
案例:
1.求给定结点在二叉树中的层次,根节点为1,若结点不在树中返回0。
思路:用括号法建立二叉树,在依次从根节点,根的左孩子结点,根的右孩子结点查找是否存在此结点,在此过程用一个全局变量记录层数,如果找到,立刻返回层数,并退出.
测试样例:
A{B{D,E},C{F,G{,H}} F 输出 3
A{B{D,E},C{F,G{,H}} A 输出 1
A{B{D,E},C{F,G{,H}} M 输出 0
代码如下:
// Created by Chenglong Shi on 2021/10/8.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
const int ma=1<<10;
int f=0,refloor;
typedef struct node{
char val;
node *l,*r;
node(char val='\0'):val(val){l=r=NULL;}
}*Bnode,btnode;
Bnode createBT(char *str){
Bnode *st=new Bnode[ma];//指向指针的指针
for(int i=0;i<ma;i++) st[i]=new btnode();
btnode *p=NULL,*root=NULL;
int index=0,len=strlen(str),k=-1,top=0;
while(index<len){
char ch=str[index];
switch(ch){
case '{':k=1; st[top++]=p; break;
case '}':top--; break;
case ',':k=2; break;
default:
p=new btnode(ch);
if(!root) root=p;
switch(k){
case 1:st[top-1]->l=p; break;
case 2:st[top-1]->r=p; break;
}
}
index++;
}
return root;
}
int find_floor(Bnode root,char &val){
if(!root) return 0;
else{
f++;
if(root->val==val) refloor=f;
find_floor(root->l,val);
find_floor(root->r,val);
f--;
}
return 0;//找到最后也没有找到
}
void pre(Bnode root){
if(root){
cout<<root->val<<" ";
pre(root->l);
pre(root->r);
}
}
char str[ma];
int main(){
char value;
cin>>str; cin>>value;
Bnode root= createBT(str);
cout<<"先序遍历:";
pre(root);
cout<<"\n"<<value<<" 在树中的层次是:";
find_floor(root,value);
cout<<refloor;
return 0;
}
2:对于不带头结点的单链表L,设计一个递归算法逆置所有结点。编写完整的程序并采用相应数据进行测试。
思路:设计链表的结点,并采用相应的数据进行连接填充,然后找到链表的尾并标记,最后在递归回溯的时候,让本结点的下一个结点的next指向本结点,然后让本节点的next指向空。
测试样例:
0 输出:-1
1 1 输出1
5 1 2 3 4 5 输出:5 4 3 2 1
代码如下:
//
// Created by Chenglong Shi on 2021/10/9.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
typedef int ElementType;
typedef struct linknode{
ElementType val;
linknode *next;
linknode(ElementType val=-1):val(val){next=NULL;}
}*Link,linknode;
int n,k;
void showlist(Link);
Link listreverse(Link);
int main(){
cin>>n;
Link head=new linknode();
linknode *tail=NULL;
for(int i=0;i<n;i++){
cin>>k;
if(i==0) {head->val=k; tail=head;}
else{
linknode *newnode=new linknode(k);
tail->next=newnode;
tail=newnode;
}
}
cout<<"链表逆置之前:\n";
showlist(head);
cout<<endl;
head=listreverse(head);
cout<<"链表逆置之后:\n";
showlist(head);
return 0;
}
void showlist(Link head){
Link p=head;
while(p){
cout<<p->val<<" ";
p=p->next;
}
}
Link listreverse(Link head){
Link newhead;
if(!head||!(head->next)) return head;
newhead=listreverse(head->next);
head->next->next=head;
head->next=NULL;
return newhead;
}
3:给出两棵树的先序和中序遍历,判断两颗二叉树是否同构
思路:设计二叉链表的结点,并根据两棵树的先序和中序遍历,递归建立二叉树,最后通过递归交换任意一棵树的左右结点,每当交换一次,判断是否与另一棵树相同,若相同,则同构,若整棵树交换完毕也不同构,则两棵树不同构。
输入样例:
8
1 2 4 5 3 6 7 8
5 4 2 1 3 6 7 8
8
1 2 4 5 3 6 8 7
4 2 5 1 8 6 3 7
输出:
false(非同构)
代码如下:
// Created by Chenglong Shi on 2021/10/11.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
typedef struct btnode{
int val;
btnode *l,*r;
btnode(int val=0):val(val){l=r=NULL;}
bool operator==(btnode *others){
return val==others->val;
}
}*Btr,btnode;
void input_val(int*,int);
Btr Build_bt(int* ,int ,int*, int ,int);//chuang jian shu
void change_Btchild(Btr);// jiao huan zuo you jie dian
void pre_show(Btr);//xian xu bian li
bool Two_bt_isSame(Btr,Btr);
int main(){
int n1;
cin>>n1;
int pre1[n1],in1[n1];
input_val(pre1,n1);
input_val(in1,n1);
int n2;
cin>>n2;
int pre2[n2],in2[n2];
input_val(pre2,n2);
input_val(in2,n2);
Btr root1= Build_bt(pre1,0,in1,0,n2);
Btr root2= Build_bt(pre2,0,in2,0,n2);
printf("the first tree's pre visit is:\n");
pre_show(root1);
printf("\nthe second tree's pre visit is:\n");
pre_show(root2);
if(Two_bt_isSame(root1,root2)) printf("\ntrue");
else printf("\nfalse");
return 0;
}
void input_val(int *arr,int n){
for(int i=0;i<n;i++) cin>>arr[i];
}
void pre_show(Btr root){
if(root){
cout<<root->val<<" ";
pre_show(root->l);
pre_show(root->r);
}
}
Btr Build_bt(int *pre,int i,int *in,int j,int len){
if(len<=0) return NULL;
int val=pre[i];
btnode *root=new btnode(val);
int p=j,k;
while(p<j+len){
if(in[p]==val) break;
p++;
}
k=p-j;
root->l= Build_bt(pre,i+1,in,j,k);
root->r= Build_bt(pre,i+k+1,in,p+1,len-k-1);
return root;
}
void change_Btchild(Btr root){
if(root){
btnode *newnode=root->l;
root->l=root->r;
root->r=newnode;
change_Btchild(root->l);
change_Btchild(root->r);
}
}
bool Two_bt_isSame(Btr root1,Btr root2){
if(!root1&&!root2) return true;
else{
int k=0;
while(root1->l!=root2->l||root1->r!=root2->r){
btnode *newnode=root1->l;
root1->l=root1->r;
root1->r=newnode;
k++;
if(k>2) break;
}
if(k>2) return false;
else{
bool m1= Two_bt_isSame(root1->l,root2->l);
bool m2= Two_bt_isSame(root1->r,root2->r);
return m1&&m2;
}
}
}
3:给出二叉树的先序和中序遍历,求所有叶子结点的和(类型为int)。
思路:设计二叉树结点,先根据先序和中序序列利用递归建立二叉树,然后声明一个记录叶子节点和的全局变量,初始值为1,然后递归的判断刚才建立的树的每个结点,若其没有左子树和右子树,则将其数值加到全局变量上,并回退,否则依次判断左右子树,直到整棵树遍历完毕。
输入样例:8
1 2 4 5 6 7 3 8
4 2 6 5 7 1 3 8
输出:25
代码如下:
// Created by Chenglong Shi on 2021/10/10.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
#define check(root) root->l==NULL&&root->r==NULL
typedef struct btnode{
int val;
btnode *l,*r;
btnode(int val=0):val(val){l=r=NULL;}
}*Btr,btnode;
int n;
Btr BuildBt(int*,int,int*,int,int);
void showBt(Btr);
int get_all_leafs(Btr);
int main(){
cin>>n;
int pre[n],in[n];
for(int i=0;i<n;i++) cin>>pre[i];
for(int i=0;i<n;i++) cin>>in[i];
Btr root= BuildBt(pre,0,in,0,n);
cout<<"preoeder:"<<endl;
showBt(root);
cout<<"\nthe sum of all leaves is as follows:\n";
cout<<get_all_leafs(root);
return 0;
}
Btr BuildBt(int *pre,int i,int *in,int j,int len){
if(len<=0) return NULL;
int val=pre[i];
btnode *root=new btnode(val);
int p=0,k=0; p=j;
while(p<j+len){
if(in[p]==val)
break;
p++;
}
k=p-j;
root->l= BuildBt(pre,i+1,in,j,k);
root->r= BuildBt(pre,i+k+1,in,p+1,len-k-1);
return root;
}
void showBt(Btr root){
if(root){
cout<<root->val<<" ";
showBt(root->l);
showBt(root->r);
}
}
int get_all_leafs(Btr root){
static int sum=0;
if(!root) return 0;
if(check(root)){sum+=root->val;cout<<"leave is"<<root->val<<endl;}
get_all_leafs(root->l);
get_all_leafs(root->r);
return sum;
}
5:求一棵二叉树的最大路径,给定中序和后序遍历序列(从根节点到叶子结点的权值之和)
思路:建立全局大根堆(存储最大路)和全局路径长度累计变量,设计二叉树的结点类型,通过中序后序递归建立二叉树,然后先判断根结点是否为空,如果空的话直接返回0,否则,继续向左右子树深入递归,在此过程将每个结点的权值累加到长度累计变量,直到判断到某个结点的左右子树均为空(叶子结点),将长度累计变量的值加入到大根堆中,然后回溯,直到所有的路径全部判断完毕,主程序最后弹出堆顶即为最大的路径。
输入样例:
9
8 4 9 2 5 1 6 3 7
8 9 4 5 2 6 7 3 1
输出:16
代码如下:
// Created by Chenglong Shi on 2021/10/10.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
#define check(root) root->l==NULL&&root->r==NULL
typedef struct btnode{
int val;
btnode *l,*r;
btnode(int val=0):val(val){l=r=NULL;}
}*Btr,btnode;
Btr Build_Bt(int*,int,int*,int,int);
void show_post(Btr);
int n,path;
priority_queue<int,vector<int>,less<int>> big_heap;
void find_path(Btr);
int main(){
cin>>n;
int in[n],post[n];
for(int i=0;i<n;i++) cin>>in[i];
for(int i=0;i<n;i++) cin>>post[i];
Btr root= Build_Bt(in,0,post,0,n);
cout<<"the post show:\n";
show_post(root);
find_path(root);
cout<<"\nthe maxlen path's length is:\n";
cout<<big_heap.top()<<endl;
return 0;
}
Btr Build_Bt(int *in,int i,int *post,int j,int len){
if(len<=0) return NULL;
int val=post[i+len-1];
btnode *root=new btnode(val);
int p=j,k=0;
while(p<j+len){
if(in[p]==val) break;
p++;
}
k=p-j;
root->l= Build_Bt(in,i,post,j,k);
root->r= Build_Bt(in,i+k,post,p+1,len-k-1);
return root;
}
void show_post(Btr root){
Btr p=root,q=NULL;
stack<btnode*> st;
do{
while(p){
st.push(p);
p=p->l;
}
q=NULL;
bool flag=true;
while(!st.empty()&&flag){
p=st.top();
if(p->r==q){
cout<<p->val<<" ";
st.pop();
q=p;
}
else{
flag=false;
p=p->r;
}
}
}while(!st.empty());
}
void find_path(Btr root){//wei di gui
if(!root) return;//ben jie dian hui tui
path+=root->val;
if(check(root)) {
big_heap.push(path);
path-=root->val;
return;
}
find_path(root->l);
find_path(root->r);
path-=root->val;//shang ceng jie dian hui tui
}
6:假设给定一字符串用字符数组存储,用递归的方式判断其是否为回文串。
思路:用字符数组存储给定的字符串,然后分别设置两个下标变量来指向字符串的头和尾部。如果两标记对应的字符相等,则第一个标记变量自增1,第二个标记变量自减1,若不相等输出false直接退出。一直递归该程序,直到第一个标记大于第二个标记。
输入样例:
abcba
输出样例:
true
输入样例:
abcdef
输出样例:
false
代码如下:
// Created by Chenglong Shi on 2021/10/11.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
const int ma=1e5+1;
char str[ma];
bool is_plalindrome(int,int);
int main(){
cin.getline(str,ma);
if(is_plalindrome(0, strlen(str)-1))
cout<<"true";
else
cout<<"false";
return 0;
}
bool is_plalindrome(int be,int en){
if(be>en) return true;
if(str[be]!=str[en]) return false;
return is_plalindrome(be+1,en-1);
}
7:.设给定一整数n和n个数,请你完成不带头结点的链表的设计和实现,并采用递归的方法逆序输出链表的所有结点的数值
思路:从链表的第一个结点进行判断,如果结点为空就直接结束程序,否则继续判断当前结点的下一个结点,当判断到是最后一个结点时,回退,并在回退时输出每个结点的值。即为逆序的序列。
输入样例:
5
1 2 3 4 5
输出样例
5 4 3 2 1
代码如下:
// Created by Chenglong Shi on 2021/10/12.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:
//
#include<bits/stdc++.h>
using namespace std;
typedef struct node{
int val;
node *next;
node(int val=0):val(val){
next=NULL;
}
}*Linknode,lnode;
int n,k;
void reverse_show(Linknode);
int main(){
cin>>n;
Linknode head=new lnode();
lnode *tail=NULL;
for(int i=0;i<n;i++){
cin>>k;
if(i==0) {
head->val=k;
tail=head;
}
else{
lnode *newnode=new lnode(k);
tail->next=newnode;
tail=newnode;
}
}
reverse_show(head);
return 0;
}
void reverse_show(Linknode head){
if(head==NULL) return;
else{
reverse_show(head->next);
cout<<head->val<<" ";
}
}
8:已知一数列的首项a1=0,后续奇数项和偶数项的计算公式分别为a2n=a2n-1+2, a2n+1=a2n-1+a2n-1.
思路:记忆化搜索,设置一个较大容量的全局变量数组,初始值均为0,如果输入的数是1则直接返回0,结束程序。如果要查询的项已经计算并保存在全局变量数组中,则也直接进行输出和退出程序。否则的话表明此项还未被计算。如果此项是偶数则进入偶数表达式,否则进入奇数的表达式进行递归。
样例输入:3
输出:2
样例输入:20
输出:513
代码如下:
// Created by Chenglong Shi on 2021/10/12.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:记忆搜索查询
//
#include<bits/stdc++.h>
using namespace std;
const int ma=1e5+5;
int st[ma],n;
int f(int,int);
int main(){
cin>>n;
cout<<f(n,1);
return 0;
}
int f(int num,int cnt){
if(num==1) return 0;
if(st[num]) return st[num];
if(cnt%2==0&&cnt>1){
st[cnt]=st[cnt-1]+2;
if(cnt==num) return st[cnt];
}
else if(cnt%2!=0&&cnt>1){
st[cnt]=st[cnt-2]+st[cnt-1]-1;
if(cnt==num) return st[cnt];
}
return f(num,cnt+1);
}
分享就到这里,希望能对大家有所帮助,哈哈😊