使用星号的Java直方图

我正在尝试创建一个利用应用程序运行程序的直方图类。

public class Histogram { String name; int max; public Histogram (String name, int max) { this.name = name; this.max = max; } int[] count = new int[max+1]; public void add(int numbers) { // Handles out of bounds case if (numbers  max) return; count[numbers]++; } public String toString() { String result = name + "\n"; for (int index = 0; index < count.length; index++) { result = result + count[index] + ": "; for (int indexStar = 0; indexStar < count[index]; indexStar++) result = result + "*"; result = result + "\n"; } return result; } } 

我的应用程序:

 public class HistogramDataCollector { public static void main (String[] args) { Histogram h = new Histogram ("Favorite Number Survey", 11); h.add(1); h.add(0); h.add(9); h.add(7); h.add(7); h.add(3); h.add(4); h.add(6); h.add(5); h.add(2); h.add(2); h.add(8); System.out.println(h); } } 

我正在努力弄清楚如何添加int数字以获得它们出现的频率来制定用星号创建的直方图。 谢谢!

你需要做的第一件事是摆脱你的所有方法之外的循环代码无关紧要。 这将不允许您的代码编译。 但是,一旦删除该代码,此类应该直接工作。 您也可以删除numbers数组,因为它没有在您的class级中使用。 只需使用count变量,你就会明白为什么。

另外需要注意的是,您需要更改构造函数和变量定义,使它们看起来像这样:

 String name; int max; int[] count; public Histogram(String name, int max) { this.name = name; this.max = max; this.count = new int[max+1]; } 

原因是因为当您创建此类的对象时, max被假定为0 。 因此,这将声明一个大小为1的数组,并且当您在构造函数中读取max变量时它不会更改。 因此,您需要将其保留为未分配,然后在构造函数内分配数组。


正如您所提到的,您对如何从此直方图类中获取其出现频率感到困惑。 记住直方图的定义。 直方图您在数据中看到的数字的频率。 类中的count数组将自动存储频率或您在数据集中看到该特定数字的次数。 您使用add()方法,此方法的输入是您要观察到的直方图中的数字。

作为直方图如何工作的一个例子,如果count[0] = 1, count[1] = 2, count[2] = 4 ,这意味着你看到0的次数是1次, 1 2次,和数据集中的2 4次。 因此,您只需迭代计数数组的每个元素以检索每个数字的频率。 鉴于您的测试器类中的上述示例,在调用各种添加方法后,每个数字的频率计数将为: count[0] = 1, count[1] = 1, count[2] = 2, count[3] = 1, count[4] = 1, count[5] = 1, count[6] = 1, count[7] = 2, count[8] = 1, count[9] = 1, count[10] = 0

count每个位置是您看到该数字的次数。 因此,对于add()方法, numbers是您看到的数字。 因此,您可以访问属于该数字的特定插槽,并将计数增加1.例如,执行h.add(0); 那么就等于count[0]++;count[0] = count[0] + 1; 。 访问插槽0 ,并增加1.我们已经看过这一次。 对于后续调用h.add ,我们会看到该特定数字是额外的时间。

但是,您的add方法不会执行错误检查 。 具体来说,如果指定的数字小于0或大于max ,则在尝试递增直方图的区间时会出现OutOfBoundsException 。 因此,如果发生这种情况,我建议您只是从方法返回而不做任何事情。 换一种说法:

 public void add(int numbers) { // Handles out of bounds case if (numbers < 0 || numbers > max) return; count[numbers]++; } 

在你的类定义中,做int count[] = new int[max+1]; 将自动将此数组的所有元素分配给0. max将是您在数据集中看到的最高数字。 确保为0索引添加1帐户,这就是它为max+1个插槽分配的原因。 我们这样做是为了确保我们能够记录数据集中所见的每个可能数字的数字频率。 从此类创建对象时,所有这些bin都将重置为0,因此您可以立即开始使用该对象。


我要注意的一件事是你说你想通过显示星号来表示bin计数来实现这个直方图。 因此,您需要将toString()方法修改为:

 public String toString() { String result = name + "\n"; for (int index = 0; index < count.length; index++) { result = result + index + ": "; // New for (int indexStar = 0; indexStar < count[index]; indexStar++) // New result = result + "*"; // New result = result + "\n"; // New } return result; } 

上面的代码将做的是,对于直方图中的每个bin,它将显示数字的频率计数,后面放置一个冒号,一个空格,然后放置与该特定数字的频率一样多的星号。 。 因此,如果你考虑我的第一个例子,你应该看到:

 0: * 1: ** 2: **** 

请注意,我只是显示频率计数的样子。 我没有正确创建此类的对象,因此直方图的名称未定义。 但是,这是您应该看到的直方图频率计数。


希望这能解决你的问题!