算法之递归

**

递归

**
学习前提:
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);
}

分享就到这里,希望能对大家有所帮助,哈哈😊

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SweetCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值