【问题标题】:Recursively Finding a Max Value in a Vector in Java在Java中递归查找向量中的最大值
【发布时间】:2016-02-07 09:03:53
【问题描述】:

所以对于一个编程类,我们需要递归地找到一个向量的最大值和最小值。我知道如何使用迭代来做到这一点,但无法弄清楚我需要做什么才能使用此分配所需的递归。如果我可以获取索引,我将能够仅使用 element at 获取最大值和最小值,但到目前为止我尝试的所有内容都会让我产生大量错误。这是我目前拥有的所有代码。

import java.util.*;
import java.io.*;

public class Lab4<E> {
    Vector <Double> data; 
    public void readData() throws FileNotFoundException
    {
        {
            Scanner console = new Scanner (System.in);
            System.out.println("Enter the data file name: ");
            String inFile = console.next();
            File fileRef = new File(inFile);
            Scanner tokens = new Scanner(fileRef);
            data = new Vector<Double>();
            while(tokens.hasNext())
                {
                Double value = tokens.nextDouble();
                data.add(value);
                }
            System.out.print("The values in the file are: "+data.toString()+"\n");
            System.out.print("The number of values in the file is: "+(data.size())+"\n");
            tokens.close();
            console.close();
        }
    }   
    public static void main(String[] args) 
            throws IOException
    {
    Lab4 fileTest = new Lab4();
    fileTest.readData();
    System.out.println(obj);
    }

    class MinMaxObject
    {
        private double max, min;
        private int maxPos, minPos;
         public MinMaxObject()
          {
            this.max =Double.MIN_VALUE;
            this.maxPos = 0;
            this.min=Double.MAX_VALUE;
            this.minPos = 0;

         }
         public MinMaxObject(double ma, int maP, double mi, int miP)
         {
            this.max = ma;
            this.maxPos = maP;
            this.min = mi;
            this.minPos = miP;
         }
        public void setMax(double newMax)
        {
            max = newMax;
        }
        public double getMax() {
            return max;
            } 
        public void setMin(double newMin)
        {
            min = newMin;
        }
        public double getMin() {
            return min;
            } 
        public void setMaxPos(int newMaxPos)
        {
            maxPos = newMaxPos;
        }
        public int getMaxPos() {
            return maxPos;
            } 
        public void setMinPos(int newMinPos)
        {
            minPos = newMinPos;
        }
        public int getMinPos() {
            return minPos;
            } 
    }
}

【问题讨论】:

    标签: java recursion vector inner-classes


    【解决方案1】:

    除非有特定要求使用Vector不要,如果是,请告诉老师将作业更新为 1998 年以后的内容。Vector 已替换为 @987654322 @ 回到 1998 年的 Java 1.2,javadoc 说:

    与新的集合实现不同,Vector 是同步的。如果不需要线程安全实现,建议使用ArrayList 代替Vector

    如果需要同步,我建议在 ArrayList 周围使用 Collections.synchronizedList() 而不是 Vector,这意味着永远不应使用 Vector,除非使用需要它的旧 API。


    Java 不支持尾递归,但还是让我解释一下,因为这将是其他支持它的语言的首选方式。

    当您使用递归时,函数调用会进入调用堆栈。最终,通过非常深的递归,您可能会耗尽堆栈空间,这将导致 StackOverflowException 并终止您的程序。

    在纯函数式编程中,所有变量都是不可变的,在不占用堆栈空间的情况下执行循环的方法是将递归调用放在方法中的最后一件事。这样,函数式编译器可以简单地跳转回到方法的开头,而无需添加到调用堆栈中,这只是可能的,因为在当前调用中没有什么可做的。

    为了使这个方法适用于必须返回列表最大值的方法,递归调用传入List、要处理的下一个索引以及到目前为止找到的最大值。在列表的末尾,它返回传入的值。

    为了方便使用,通常有一个引入方法,所以调用者不必设置额外的参数。

    public static Integer max(List<Integer> list) {
        if (list.isEmpty())
            return null;
        return max(list, 1, list.get(0));
    }
    private static final Integer max(List<Integer> list, int index, Integer maxSoFar) {
        if (index == list.size())
            return maxSoFar;
        Integer value = list.get(index);
        Integer maxValue = (value.compareTo(maxSoFar) > 0 ? value : maxSoFar);
        return max(list, index + 1, maxValue); // tail-recursive call
    }
    

    上面的代码只会在List通过索引直接访问的对象上表现良好,例如ArrayList,但在LinkedList这样的列表上表现不佳。

    对于所有List 对象和任何其他Collection 对象,您可以改用Iterator

    在这里,我还将展示如何使用Optional

    public static Optional<Integer> max(Iterable<Integer> coll) {
        Iterator<Integer> iter = coll.iterator();
        if (! iter.hasNext())
            return Optional.empty();
        return Optional.of(max(iter, iter.next()));
    }
    private static final Integer max(Iterator<Integer> iter, Integer maxSoFar) {
        if (! iter.hasNext())
            return maxSoFar;
        Integer value = iter.next();
        return max(iter, (value.compareTo(maxSoFar) > 0 ? value : maxSoFar));
    }
    

    要同时获取最小值和最大值,您需要一个类来返回这两个值。

    也可以更新代码以处理 Comparable 的任何内容。

    public static final class MinMax<T> {
        private final T min;
        private final T max;
        MinMax(T min, T max) {
            this.min = min;
            this.max = max;
        }
        public T getMin() {
            return this.min;
        }
        public T getMax() {
            return this.max;
        }
    }
    public static <T extends Comparable<T>> Optional<MinMax<T>> minMax(Iterable<T> coll) {
        Iterator<T> iter = coll.iterator();
        if (! iter.hasNext())
            return Optional.empty();
        T value = iter.next();
        return Optional.of(minMax(iter, value, value));
    }
    private static final <T extends Comparable<T>> MinMax<T> minMax(Iterator<T> iter, T minSoFar, T maxSoFar) {
        if (! iter.hasNext())
            return new MinMax<>(minSoFar, maxSoFar);
        T value = iter.next();
        return minMax(iter, (value.compareTo(minSoFar) < 0 ? value : minSoFar),
                            (value.compareTo(maxSoFar) > 0 ? value : maxSoFar));
    }
    

    【讨论】:

    • 感谢您的介绍。我最终能够让它工作。是的,他坚持我们使用向量,并且关于该主题的每条建议都使用数组列表。
    【解决方案2】:

    您可以使用以下代码递归获取向量的最小值:

    static double min(Vector<Double> v, int index) {
        if (index == v.size() - 1) {
            return v.get(index);
        }
        double val = min(v, index + 1);
    
        if (v.get(index) < val) {
            return v.get(index);
        } else {
            return val;
        }
    }
    

    你可以用同样的方法递归地找到最大值,只需在最后一个 if 语句中将

    【讨论】:

      【解决方案3】:

      使用一种辅助方法,该方法采用索引参数和您的最大/最小对象。代码应该是不言自明的:

      public MinMaxObject getMinMax(Vector<Double> vector) {
          MinMaxObject minMax = new MinMaxObject();
          getMinMaxAux(vector, minMax, 0);
          return minMax;
      }
      
      public void getMinMaxAux(Vector<Double> vector, MinMaxObject minMax, int index) {
          if(index < vector.size())
          {
              double value = vector.get(index);
              if(value > minMax.getMax())
              {
                  minMax.setMax(value);
                  minMax.setMaxPos(index);
              }
              if(value < minMax.getMin())
              {
                  minMax.setMin(value);
                  minMax.setMinPos(index);
              }
              getMinMaxAux(vector, minMax, index + 1);
          }
      }
      

      您也可以选择不在参数中传递MinMaxObject,而是从递归调用中获取。 MinMaxObject 将在您到达矢量末尾时创建。但它会产生可能有些混乱的代码。 如果您想尝试一下,这是一个很好的练习。

      【讨论】:

      • 感谢您的建议,我的最终方法最终看起来很像这样。
      【解决方案4】:

      但是向量中有直接的方法可以找到最大值

      公共类主{

      public static void main(String[] args) {

      Vector<Double> v = new Vector<Double>();
      v.add(new Double("3.0"));
      v.add(new Double("4.0"));
      Object obj = Collections.max(v);
      System.out.println(obj);
      

      } }

      【讨论】:

      • 是的,但他要求我们递归地完成任务。
      猜你喜欢
      • 2021-11-11
      • 1970-01-01
      • 2021-12-08
      • 2020-06-06
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      相关资源
      最近更新 更多