遍历递归树求递推数列通项

考虑K阶变系数线性递推方程:

现给定初值a1,a2,—,ak和n>k,要求编程打印an,an-1,—,ak+1的值

该问题用常规的迭代法非常容易解决,现在要考虑的是用遍历递归调用树的方法求解。n=7,k=3时,递归调用树为

package programm;           //遍历递归树中所有节点,相同值会重复计算
import java.util.*;

public class RecursionTree 
{

    public static void main(String[] args)
    {
        final int K=3;
        final int N=7;
        int[] initial=new int[K];
        for (int i=0; i<K; i++)
            initial[i]=i+1;
        
        Stack<Node> stack=new Stack<Node>();
        stack.push(new Node(0, 0, N));
        boolean TF=true;
        int sign=0, n=stack.getTop().getIndex();
        
        while(!stack.isEmpty())
        {
            if (1<=n&&n<=K)
            {
                stack.getTop().setSum(stack.getTop().getSum()+initial[n-1]*(stack.getTop().getIndex()+stack.getTop().getFlag()));
                TF=false;
                n=stack.getTop().getIndex();
            }
            else
            { 
                if (TF==false)
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);
                    
                    if (stack.getTop().getFlag()>K)
                    {
                        Node temp=stack.pop();
                        temp.setSum(temp.getSum()+temp.getIndex());
                        
                        if (stack.isEmpty())
                        {
                            System.out.println("The "+temp.getIndex()+"nd item is "+temp.getSum());
                        }
                        else
                        {                
                            if (stack.getTop().getFlag()==1 && temp.getIndex()>sign)
                            {
                                sign=temp.getIndex();
                                System.out.println("The "+temp.getIndex()+"nd item is "+temp.getSum());
                            }
                        
                            stack.getTop().setSum(stack.getTop().getSum()+temp.getSum()*(stack.getTop().getIndex()+stack.getTop().getFlag()));
                            n=stack.getTop().getIndex();
                            TF=false;
                        }
                    }
                    else
                    {
                        if ((n=stack.getTop().getIndex()-stack.getTop().getFlag())>K)
                        {
                            stack.push(new Node(0, 0, n));
                            TF=true;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                else
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);
                    if ((n=stack.getTop().getIndex()-1)>K)
                    {
                        stack.push(new Node(0, 0, n));
                        TF=true;
                    }
                    else
                    {
                        continue;
                    }
                }
            }
        }
    }

}

class Node
{
    private int sum;
    private int flag;
    private int index;    
    
    public Node(int sum, int flag, int index)
    {
        this.sum=sum;
        this.flag=flag;
        this.index=index;
    }
    
    public int getSum()
    {
        return sum;
    }
    
    public void setSum(int sum)
    {
        this.sum=sum;
    }
    
    public int getFlag()
    {
        return flag;
    }
    
    public void setFlag(int flag)
    {
        this.flag=flag;
    }
    
    public int getIndex()
    {
        return index;
    }
}

class Stack<E>
{
    ArrayList<E> list=new ArrayList<E>();
    
    public boolean isEmpty()
    {
        return list.isEmpty();    
    }
    
    public int getSize()
    {
        return list.size();
    }
    
    public E getTop()
    {
        return list.get(getSize()-1);
    }
    
    public E pop()
    {
        E interval=list.get(getSize()-1);
        list.remove(getSize()-1);
        return interval;
    }
    
    public void push(E Ob)
    {
        list.add(Ob);
    }
}

运行结果:

 以上方法的问题是,相同的项会被重复计算多次,如a4被重复计算了三次,所以以上方法需要改进。用数组保存已求出项的值,遍历
到相同项时直接从数组中找到并使用其值即可。要实现这一点,需要修改源程序41行,48行,60-61行。修改后的代码如下:
程序二:

package programm;   //不遍历递归树中所有节点,相同值不会重复计算
import java.util.*;

public class RecursionTree 
{

    public static void main(String[] args)
    {
        final int K=3;   //递推方程阶数
        final int N=7;   //要求的部分数列中下标最大的项的下标
        int[] initial=new int[K];   //初值a1----ak
        for (int i=0; i<K; i++)    //令初值a1----ak分别为1,2---,k
            initial[i]=i+1;
        
        Stack<Node> stack=new Stack<Node>();   //建立Node类型栈对象
        stack.push(new Node(0, 0, N));     //递归树根节点压入栈,该节点flag=sum=0,index=N
        boolean TF=true;    //true向前进至下一层,false回溯至上一层
        int sign=0, n=stack.getTop().getIndex();   //sign记录当前已遍历节点中下标最大的节点,n初始化为根节点下标
        int[] result=new int[N-K];   //记录ak+1---aN项值的数组
        
        while(!stack.isEmpty())   //栈不空
        {
            if (1<=n&&n<=K)  //到达递归树中可直接写出值的叶子结点
            {
                stack.getTop().setSum(stack.getTop().getSum()+initial[n-1]*(stack.getTop().getIndex()+stack.getTop().getFlag()));  //将叶子结点值乘以系数累加至父节点
                TF=false;
                n=stack.getTop().getIndex();    //回溯
            }
            else
            { 
                if (TF==false)
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);   //当前节点flag增一,试探下一子节点
                    
                    if (stack.getTop().getFlag()>K)    //当前节点所有子节点均试探完毕
                    {
                        Node temp=stack.pop();   //从栈中弹出当前节点
                        temp.setSum(temp.getSum()+temp.getIndex());   //加上尾数f(n),得到当前节点的值
                        
                        if (stack.isEmpty())  //栈空,temp引用根节点,根节点值已求出,存放在temp的sum中
                        {
                            result[N-K-1]=temp.getSum();   //在数组result中存放根节点即aN的值
                            System.out.println("The "+temp.getIndex()+"nd item is "+temp.getSum());  //打印aN的值
                        }
                        else
                        {                
                            if (stack.getTop().getFlag()==1 && temp.getIndex()>sign)  //找到当前已遍历节点中下标最大节点
                            {
                                sign=temp.getIndex();   //设置新的最大下标
                                result[temp.getIndex()-K-1]=temp.getSum();  //当前节点值存放至result数组中
                                System.out.println("The "+temp.getIndex()+"nd item is "+temp.getSum());  //打印当前节点值
                            }
                        
                            stack.getTop().setSum(stack.getTop().getSum()+temp.getSum()*(stack.getTop().getIndex()+stack.getTop().getFlag()));  //当前节点值乘以系数累加至父节点
                            n=stack.getTop().getIndex();
                            TF=false;  //回溯
                        }
                    }
                    else
                    {
                        if ((n=stack.getTop().getIndex()-stack.getTop().getFlag())>K)  //前进至非叶子结点
                        {
                            stack.getTop().setSum(stack.getTop().getSum()+result[n-K-1]*(stack.getTop().getIndex()+stack.getTop().getFlag()));  //当前节点值之前已算出,从数组result中找出该值乘以系数累加至父节点
                            n=stack.getTop().getIndex();
                            TF=false;      //回溯
                        }
                        else
                        {
                            continue;  //直接进至下一轮循环,累加叶子节点值和系数乘积至父节点
                        }
                    }
                }
                else
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1); //进至新的一层,当前节点flag增一试探下一层节点
                    if ((n=stack.getTop().getIndex()-1)>K) //下一层第一个节点非叶子
                    {
                        stack.push(new Node(0, 0, n));    //该节点压入栈
                        TF=true;  
                    }                                      
                    else
                    {
                        continue;    //同上
                    }
                }
            }
        }
    }

}

class Node    //递归树节点类
{
    private int sum;     //当前节点值
    private int flag;    //当前节点的父节点下标和当前节点下标之差
    private int index;    //当前节点下标
    
    public Node(int sum, int flag, int index)   //构造方法
    {
        this.sum=sum;
        this.flag=flag;   
        this.index=index;
    }
    
    public int getSum()
    {
        return sum;
    }
    
    public void setSum(int sum)
    {
        this.sum=sum;
    }
                                    //访问器和修改器
    public int getFlag()
    {
        return flag;
    }
    
    public void setFlag(int flag)
    {
        this.flag=flag;
    }
    
    public int getIndex()
    {
        return index;
    }
}

class Stack<E>            //泛型栈类
{
    ArrayList<E> list=new ArrayList<E>();
    
    public boolean isEmpty()
    {
        return list.isEmpty();    
    }
    
    public int getSize()
    {
        return list.size();
    }
    
    public E getTop()
    {
        return list.get(getSize()-1);
    }
    
    public E pop()
    {
        E interval=list.get(getSize()-1);
        list.remove(getSize()-1);
        return interval;
    }
    
    public void push(E Ob)
    {
        list.add(Ob);
    }
}

可以验证运行结果和程序一相同,但是节省了运行时间
删掉程序一37行,修改24行和51行可以得到程序三,用于计算递推数列an=an-1+—an-kn>k a1=1—ak=k当给定n>k时an,—,ak+1的值。
程序三(n=7, k=2, a1=1, a2=2):

package programm;          //an=an-1+---an-k型递归式求解,遍历所有节点
import java.util.*;

public class RecursionTree 
{

    public static void main(String[] args)
    {
        final int K=2;
        final int N=7;
        int[] initial=new int[K];
        for (int i=0; i<K; i++)
            initial[i]=i+1;
        
        Stack<Node> stack=new Stack<Node>();
        stack.push(new Node(0, 0, N));
        boolean TF=true;
        int sign=0, n=stack.getTop().getIndex();
        
        while(!stack.isEmpty())
        {
            if (1<=n&&n<=K)
            {
                stack.getTop().setSum(stack.getTop().getSum()+initial[n-1]);
                TF=false;
                n=stack.getTop().getIndex();
            }
            else
            { 
                if (TF==false)
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);
                    
                    if (stack.getTop().getFlag()>K)
                    {
                        Node temp=stack.pop();
                        
                        if (stack.isEmpty())
                        {
                            System.out.println("The "+temp.getIndex()+"nd item is "+temp.getSum());
                        }
                        else
                        {                
                            if (stack.getTop().getFlag()==1 && temp.getIndex()>sign)
                            {
                                sign=temp.getIndex();
                                System.out.println("The "+temp.getIndex()+"nd item is "+temp.getSum());
                            }
                        
                            stack.getTop().setSum(stack.getTop().getSum()+temp.getSum());
                            n=stack.getTop().getIndex();
                            TF=false;
                        }
                    }
                    else
                    {
                        if ((n=stack.getTop().getIndex()-stack.getTop().getFlag())>K)
                        {
                            stack.push(new Node(0, 0, n));
                            TF=true;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                else
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);
                    if ((n=stack.getTop().getIndex()-1)>K)
                    {
                        stack.push(new Node(0, 0, n));
                        TF=true;
                    }
                    else
                    {
                        continue;
                    }
                }
            }
        }
    }

}

class Node
{
    private int sum;
    private int flag;
    private int index;    
    
    public Node(int sum, int flag, int index)
    {
        this.sum=sum;
        this.flag=flag;
        this.index=index;
    }
    
    public int getSum()
    {
        return sum;
    }
    
    public void setSum(int sum)
    {
        this.sum=sum;
    }
    
    public int getFlag()
    {
        return flag;
    }
    
    public void setFlag(int flag)
    {
        this.flag=flag;
    }
    
    public int getIndex()
    {
        return index;
    }
}

class Stack<E>
{
    ArrayList<E> list=new ArrayList<E>();
    
    public boolean isEmpty()
    {
        return list.isEmpty();    
    }
    
    public int getSize()
    {
        return list.size();
    }
    
    public E getTop()
    {
        return list.get(getSize()-1);
    }
    
    public E pop()
    {
        E interval=list.get(getSize()-1);
        list.remove(getSize()-1);
        return interval;
    }
    
    public void push(E Ob)
    {
        list.add(Ob);
    }
}

运行结果:

 显然,所求得的即为斐波那契数列的第4-8项
为了便于读者理解程序一二三,下面给出一个经过简化的程序四,实现思想和程序一二三基本相同且功能和程序三相同
程序四(n=7, k=2, a1=1, a2=2):不难验证运行结果和程序三是一致的

package RecursionTree;    //简化版的an=an-1+---an-k型递归式求解,遍历所有节点
import java.util.*;

public class recursiontree
{
    public static void main(String[] args) 
    {
        final int K=2;
        final int N=7;
        int[] initial=new int[K];
        for (int i=0; i<K; i++)
            initial[i]=i+1;
        
        Stack<Node> stack=new Stack<Node>();
        stack.push(new Node(0, N));
        boolean TF=true;
        int sum=0;
        
        while (!stack.isEmpty())
        {
            if (1<=stack.getTop().getIndex() && stack.getTop().getIndex()<=K)
            {
                sum+=initial[stack.getTop().getIndex()-1];
                stack.pop();
                TF=false;
            }
            else
            {
                if (TF==false)
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);
                    if (stack.getTop().getFlag()>K)
                    {
                        stack.pop();
                        TF=false;
                    }
                    else
                    {
                        stack.push(new Node(0, stack.getTop().getIndex()-stack.getTop().getFlag()));
                        TF=true;
                    }
                }
                else
                {
                    stack.getTop().setFlag(stack.getTop().getFlag()+1);
                    stack.push(new Node(0, stack.getTop().getIndex()-1));
                    TF=true;
                }
            }
        }
        System.out.println("The "+N+"nd item is "+sum);
    }
}

class Node
{
    private int flag;
    private int index;    
    
    public Node(int flag, int index)
    {
        this.flag=flag;
        this.index=index;
    }    
    
    public int getFlag()
    {
        return flag;
    }
    
    public void setFlag(int flag)
    {
        this.flag=flag;
    }
    
    public int getIndex()
    {
        return index;
    }
}

class Stack<E>
{
    ArrayList<E> list=new ArrayList<E>();
    
    public boolean isEmpty()
    {
        return list.isEmpty();    
    }
    
    public int getSize()
    {
        return list.size();
    }
    
    public E getTop()
    {
        return list.get(getSize()-1);
    }
    
    public E pop()
    {
        E interval=list.get(getSize()-1);
        list.remove(getSize()-1);
        return interval;
    }
    
    public void push(E Ob)
    {
        list.add(Ob);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值