Java开发网 |
注册 |
登录 |
帮助 |
搜索 |
排行榜 |
发帖统计
|
您没有登录 |
» Java开发网 » Java GUI 设计
» Swing
打印话题 寄给朋友 订阅主题 |
作者 | 与表格对应的数组越界异常 |
火山一角
发贴: 27 积分: 0 |
于 2006-05-26 12:43
下面是我自己写的一个程序,用于解决运筹学中的运输问题。当输入下图所示数据时,程序快执行完成时显示数组越界异常,哪个高手帮我看一下应该怎么改。 表格中输入的数组如下(右下角不用输入): 10 20 5 9 10 5 2 10 8 30 6 6 1 20 7 10 4 2 8 6 3 7 5 9 4 4 6 2 4 程序代码如下: Transport.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; public class Transport extends JFrame implements ActionListener { private JPanel contentPane; private JPanel producingArea; private JPanel sellArea; private JPanel numPanel; private JPanel methodPanel; private JPanel tablePanel; public JButton sure; public static JButton dataInputSure;//静态变量可以通过类名.变量名进行调用 public static JButton minElement; public static JButton vogel; private JComboBox produceBox; private JComboBox sellBox; public int rowNum=2;public int columnNum=2; public String[][] transportCost; JTable table = null; DefaultTableModel defaultModel; public Transport() { contentPane = (JPanel)getContentPane(); } public void init() { setTitle("运输问题"); setSize(300, 200); String[] name = {"运费","销地1","销地2","产量"}; transportCost = new String[3][4]; for(int i=0;i<2;i++) transportCost[i][0]="产地"+(i+1); transportCost[2][0]="销量"; produceBox = new JComboBox(); for(int i = 2; i <= 5; i++) produceBox.addItem(new Integer(i)); produceBox.addActionListener(this); producingArea = new JPanel(); producingArea.add(new JLabel("产地数量")); producingArea.add(produceBox); sellBox = new JComboBox(); for(int j = 2; j <= 8; j++) sellBox.addItem(new Integer(j)); sellBox.addActionListener(this); sellArea = new JPanel(); sellArea.add(new JLabel("销地数量")); sellArea.add(sellBox); sure = new JButton("确定"); sure.addActionListener(this); defaultModel = new DefaultTableModel(transportCost,name); table = new JTable(defaultModel); table.setPreferredScrollableViewportSize(new Dimension(400,80)); table.setCellSelectionEnabled(true); JScrollPane jscrollpane = new JScrollPane(table); minElement = new JButton("最小元素法"); //minElement.addActionListener(new SolvingMethod()); vogel = new JButton("伏格尔法"); vogel.addActionListener(new SolvingMethod()); dataInputSure = new JButton("数据输入完毕"); dataInputSure.addActionListener(new SolvingMethod(table)); numPanel = new JPanel(); numPanel.setLayout(new BorderLayout()); numPanel.add(producingArea, "West"); numPanel.add(sellArea, "Center"); numPanel.add(sure, "East"); methodPanel = new JPanel(); methodPanel.setLayout(new BorderLayout()); methodPanel.add(minElement, "Center"); methodPanel.add(vogel, "East"); methodPanel.add(dataInputSure, "West"); contentPane.add(numPanel, "North"); contentPane.add(jscrollpane, "Center"); contentPane.add(methodPanel, "South"); } public void actionPerformed(ActionEvent e) { if(e.getSource()==produceBox) { rowNum=2+produceBox.getSelectedIndex(); } if(e.getSource()==sellBox) { columnNum=2+sellBox.getSelectedIndex(); } if(e.getSource()==sure) { for(int i=0;i<produceBox.getSelectedIndex();i++) { String[] addRow={"产地"+(3+i)}; defaultModel.insertRow(2+i,addRow);//在一个特定的位置插入行 } /*******没有插入列的方法,因此需要先删除一列或几列,再增加列才能实现*/ int columncount = defaultModel.getColumnCount()-1; if(columncount >= 0)//若columncount<0代表已经没有任何列了。 { TableColumnModel columnModel = table.getColumnModel(); TableColumn tableColumn = columnModel.getColumn(columncount); columnModel.removeColumn(tableColumn); defaultModel.setColumnCount(columncount); } for(int i=0;i<sellBox.getSelectedIndex();i++) { defaultModel.addColumn("销地"+defaultModel.getColumnCount()); } defaultModel.addColumn("产量"); System.out.println("数据输入结束后要让表格处于非输入状态再确认。"); sure.removeActionListener(this); } } public static void main(String args[]) { Transport transport = new Transport(); try { transport.init(); } catch(Exception exception) { } transport.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); transport.setVisible(true); } } SolvingMethod.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; class SolvingMethod implements ActionListener { JTable table; static int row;static int column; static int originalData[][] = {};//存放用户输入的数据 public SolvingMethod(){}//不同的按钮调用不同的构造方法进行事件处理 public SolvingMethod(JTable table) { this.table = table; } public void actionPerformed(ActionEvent e) { if(e.getSource()==Transport.dataInputSure) { row=table.getRowCount(); column=table.getColumnCount(); System.out.println("在平衡问题中 row="+row+" column="+column); originalData=new int[row][column-1]; for(int i=0;i<row;i++) for(int j=1;j<column;j++) { String cost=(String)table.getValueAt(i, j); if(cost==null) originalData[i][j-1]=0; else originalData[i][j-1]=Integer.parseInt(cost); } } if(e.getSource()==Transport.minElement) { MinElement method=new MinElement(originalData,row-1,column-2); //originalData的大小为row*(column-1),最大下标应为[row-1][column-2] method.init(method.b,method.row,method.column); method.setSize(400,150); method.setVisible(true); method.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } if(e.getSource()==Transport.vogel) { Vogel method=new Vogel(originalData,row-1,column-2); method.init(method.b,method.row,method.column); method.setSize(400,150); method.setVisible(true); method.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } } Vogel.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; class Vogel extends JFrame//一开始就采用该方法并没有得到正确结果,该方法有误 { JTable resultTable; JLabel instrction; JLabel resultLabel; Container contentPane; int b[][]={}; static int row;static int column;int result=0; String resultString=""; public Vogel(int originalData[][],int row,int column) { int m=0,n=0,i,j,min,secondMin,delRow=0,delCol=0; int max_rowMinus,max_columnMinus,totalProduction=0,totalSale=0; int a[][]=new int[row+2][column+2]; this.row=row;this.column=column; /***************** 判断该运输问题是否为平衡问题 ********************/ for(i=0;i<row;i++) for(j=0;j<column;j++) a[i][j]=originalData[i][j]; // 1。复制运费部分 // 2。求总销量和总产量 for(i=0;i<row;i++) totalProduction+=originalData[i][column]; for(j=0;j<column;j++) totalSale+=originalData[row][j]; // 3。比较产量和销量大小 if(totalProduction>totalSale) { a[row][column]=totalProduction-totalSale; for(i=0;i<row;i++) a[i][column]=0; column++; //产量大于销量,增加一虚拟销地,产量为二者之差,运费为0 } if(totalProduction<totalSale) { a[row][column]=totalSale-totalProduction; for(j=0;j<column;j++) a[row][j]=0; row++; } System.out.println("row="+row+" column="+column); // 4。将originalData中的产量和销量赋给a,经过上步row或column的值发生了改变 for(i=0;i<this.row;i++) a[i][column]=originalData[i][this.column]; for(j=0;j<this.column;j++) a[row][j]=originalData[this.row][j]; this.row=row;this.column=column; //刷新row或column的值 int rowData[] =new int[column];int columnData[] =new int[row]; int rowMinus[]=new int[row];int columnMinus[]=new int[column];//存放行差和列差 for(; ; ) { //*********1. 求行差和列差,分别存放到数组rowMinus[]和columnMinus[]中 for(i=0;i<row;i++)//对所有的行求行差 { /*************************************************************************************************** 先前采用的寻找最小值和次小值代码如下: for(j=0;j<column;j++) if(a[i][j]<min&&a[i][j]!=0)//如果某一列被划掉则任一行中必有0格,此时不能认为min=0 { secondMin=min; //最小值变为次小值 min=a[i][j]; } 缺点:如果一开始就碰到了最小值则次小值会被认为是100(语句声明部分有min=100,secondMin=100)。 改进方法:对行中元素进行由小到大排序,则第一个为最小,第二个为次小 ****************************************************************************************************/ /* 冒泡法排序过程中有大量的数据发生交换,直接进行排序会严重影响最终结果。 * 可以将行中数据保存到一个数组中,然后对该数组进行排序 *********/ for(j=0;j<column;j++) rowData[j]=a[i][j]; //如果行中第一个元素为-1,则表示第一列或该行已经被划掉,因此需要保证第一个元素不是-1 for(j=2;j<column;j++) if(rowData[0]==-1&&rowData[j]>=0)//rowData[0]!=-1排除第一列被划掉 { rowData[0]=rowData[j];rowData[j]=-1;break; }//最小值所在位置中的数不能是-1 //第一个元素非-1跳出循环。如果这些语句没有执行则表明该行已经被划,下面语句也可以保证行差是0 for(j=2;j<column;j++) if(rowData[1]==-1&&rowData[j]>=0)//rowData[1]!=-1排除第二列被划掉 { rowData[1]=rowData[j];rowData[j]=-1;break; }//次小值所在位置中的数不能是-1 for(j=0;j<2;j++)//对数组进行由小到大排序,只要找出两个值即可,但是需要它们不被划掉 。 for(int k=j+1;k<column;k++) if(rowData[j]>rowData[k]&&rowData[k]>=0) { int t=rowData[j];rowData[j]=rowData[k];rowData[k]=t; } min=rowData[0];secondMin=rowData[1]; rowMinus[i]=secondMin-min;//行差存放到数组rowMinus[]中 System.out.println("i="+i+" min="+min+" secondMin="+secondMin+" rowMinus="+rowMinus[i]); } for(j=0;j<column;j++) { for(i=0;i<row;i++) columnData[i]=a[i][j]; for(i=2;i<row;i++) if(columnData[0]==-1&&columnData[i]>=0) { columnData[0]=columnData[i];columnData[i]=0;break; } for(i=2;i<row;i++) if(columnData[1]==-1&&columnData[i]>=0) { columnData[1]=columnData[i];columnData[i]=0;break; } for(i=0;i<2;i++) for(int k=i+1;k<row;k++) if(columnData[i]>columnData[k]&&columnData[k]>=0) { int t=columnData[i];columnData[i]=columnData[k];columnData[k]=t; } min=columnData[0];secondMin=columnData[1]; columnMinus[j]=secondMin-min;//列差分别存放到数组columnMinus[]中 System.out.println("j="+j+" min="+min+" secondMin="+secondMin+" columnMinus="+columnMinus[j]); } //***********2. 求最大差值,分别求出行差和列差最大值进行比较即可 max_rowMinus=max_columnMinus=-1; for(i=0;i<row;i++)//求行差最大值 if(max_rowMinus<rowMinus[i]) { //找出最大和次大值是为了避免最大差值相等且同为行差或列差 max_rowMinus=rowMinus[i]; m=i; //记住行差最大值所在的行标 } for(j=0;j<column;j++) if(max_columnMinus<columnMinus[j]) { max_columnMinus=columnMinus[j]; n=j; } /***************** 找出最大差值所对应的最小运费并定位 ******************/ min=100;//对min进行初始化 if(max_rowMinus>=max_columnMinus) { //行差最大值为最大,其行标就是m,故只要找到列标即可实现定位 for(j=0;j<column;j++) if(a[m][j]>=0&&a[m][j]<min) { n=j;min=a[m][n]; }//对行差最大的行来说min<secongMin一定成立,故约束条件不取等号 } else { for(i=0;i<row;i++) if(a[i][n]>=0&&a[i][n]<min) { m=i;min=a[m][n]; } } int b[][]=new int[row][column]; //************3. 划去行或列,在数组b[][]中填结果。以后各步与最小元素法步骤相同 if(a[m][column]>=a[row][n]) { b[m][n]=a[row][n]; result=result+b[m][n]*a[m][n]; resultString=resultString+b[m][n]+"*"+a[m][n]+"+"; System.out.println("resultString="+resultString); a[m][column]-=a[row][n]; for(i=0;i<=row;i++) a[i][n]=-1; System.out.println("划掉了第"+(n+1)+"列"); delCol++; if(delCol==column-1) break; } else { b[m][n]=a[m][column]; result=result+b[m][n]*a[m][n]; resultString=resultString+b[m][n]+"*"+a[m][n]+"+"; System.out.println("resultString="+resultString); a[row][n]-=a[m][column]; for(j=0;j<=column;j++) a[m][j]=-1; System.out.println("划掉了第"+(m+1)+"行"); delRow++; if(delRow==row-1) break; } /* for(i=0;i<row;i++)//输出每一步所得的结果 { for(j=0;j<column;j++) { if(b[i][j]==0) System.out.print(" "); else System.out.print(" "+b[i][j]); } System.out.println(""); }*/ }//经多次划掉行或者列之后,剩一行或者一列 //以下是找出未划的行或者列,在其中填入数字 if(delCol==column-1) { for(j=0;j<column;j++) if(a[row][j]>=0) { System.out.println("第"+(j+1)+"列没有被划掉"); for(i=0;i<row;i++) if(a[i][column]>=0) { b[i][j]=a[i][column]; result=result+b[i][j]*a[i][j]; resultString=resultString+b[i][j]+"*"+a[i][j]+"+"; } }//未删除列已经找到,算法终止 } else { for(i=0;i<row;i++) if(a[i][column]>=0) { for(j=0;j<column;j++) if(a[row][j]>=0) { b[i][j]=a[row][j]; result=result+b[i][j]*a[i][j]; resultString=resultString+"+"+b[i][j]+"*"+a[i][j]; } } } System.out.println("最终运输方案如下:"); for(i=0;i<row;i++) { for(j=0;j<column;j++) System.out.print(" "+b[i][j]); System.out.println(""); } resultString=resultString.substring(0,resultString.length()-1);//去掉最后一个多余的加号 System.out.println("利用Vogel法得到的结果为:"+resultString+"="+result); this.b=b; } public void init(int b[][],int row,int column) { instrction=new JLabel("利用Vogel法得到的运输方案如下表",JLabel.CENTER); resultLabel=new JLabel("目标函数 Z="+resultString+"="+result,JLabel.CENTER); resultTable=new JTable(row,column); for(int i=0;i<row;i++) for(int j=0;j<column;j++) resultTable.setValueAt(String.valueOf(b[i][j]),i,j); setTitle("伏格尔法"); contentPane =getContentPane(); contentPane.add(instrction, "North"); contentPane.add(resultTable, "Center"); contentPane.add(resultLabel, "South"); } } 附件是关于Vogel法解题的基本原理和步骤,如果看不懂该程序中算法的话建议先看一下PPT文件,谢谢。 4.运输问题.ppt (846.0k)
火山一角 edited on 2006-05-26 21:27
|
已读帖子 新的帖子 被删除的帖子 |
Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1 客服电话 18559299278 客服信箱 714923@qq.com 客服QQ 714923 |