package cn.xf.algorithm.ch06ChangeRule; import java.util.ArrayList; import java.util.List; import org.junit.Test; import cn.xf.util.GenericPair; /** * * 功能:高斯消元法,也就是多元数据矩阵,依次吧每列的其他行数据消去为0,然后求出一个元的解,然后就可以根据这个数据来递推出其他元的解 * @author xiaofeng * @date 2017年7月1日 * @fileName GaussianEliminationMethod.java * */ public class GaussianEliminationMethod { /** * 这个有缺陷,如果datas.get(i).get(i)为0,那么就会出错 * @param datas */ public void forwardElimination(List<List<Double>> datas) { if(datas.size() <= 0) { return; } //方程式消除数据 for(int i = 0; i < datas.size(); ++i) { //遍历所有行,以这一行,往后消除首项的参数 for(int j = i + 1; j < datas.size(); ++j) { //遍历后面的行,开始遍历 for(int k = datas.get(j).size() - 1; k >= i; --k) { //当前行的最后,往前遍历,然后把每行的对应的第i列的系数消除 double value = datas.get(j).get(k) - datas.get(i).get(k) * datas.get(j).get(i) / datas.get(i).get(i); datas.get(j).set(k, value); } } } } /** * 这个的思路就是从每列的最大的作为开始行的基准行,然后进行高斯消元 * @param datas */ public void betterForwardElimination(List<List<Double>> datas) { if(datas.size() <= 0) { return; } //首先遍历对角线的数据,因为对角线之前的数据都要归并为0的 //遍历所有的列,进行消元 for(int column = 0; column < datas.get(0).size(); ++column) { //一个变量存放,这列中绝对值最大的值得哪一行 int maxValueRow = column; //遍历后面的所有行,比较绝对值大小 for(int afterRow = maxValueRow; afterRow < datas.size(); ++afterRow) { if(Math.abs(datas.get(afterRow).get(column)) > Math.abs(datas.get(maxValueRow).get(column))) { //吧绝对值大的行,赋值给他 maxValueRow = afterRow; } } //吧当前基准行和其他行进行交换 for(int swapColumn = column; swapColumn < datas.get(0).size(); ++swapColumn) { if(column >= datas.size()) { break; } //吧最大值得行和当前基准行进行交换 GenericPair<Integer, Integer> first = new GenericPair<Integer, Integer>(); first.setFirst(column); first.setSecond(swapColumn); GenericPair<Integer, Integer> second = new GenericPair<Integer, Integer>(); second.setFirst(maxValueRow); second.setSecond(swapColumn); swap(datas, first, second); } //遍历每一行,除以交换之后的基准,从后面行开始,i,i------------------------------------------------------------------------------------------------------------------ for(int afterRowr = column + 1; afterRowr < datas.size(); ++afterRowr) { double temp = datas.get(afterRowr).get(column) / datas.get(column).get(column); //用这个除数,排除交换之后的所有行的这个列的数据 for(int rowChu = column; rowChu < datas.get(afterRowr).size(); ++rowChu) { //每行的数据减去,基础行和temp的乘数 double resultValue = datas.get(afterRowr).get(rowChu) - datas.get(column).get(rowChu) * temp; datas.get(afterRowr).set(rowChu, resultValue); } } } } public static void swap(List<List<Double>> datas, GenericPair<Integer, Integer> first, GenericPair<Integer, Integer> second) { if(datas.size() <= 0) { return; } Double temp = datas.get(first.getFirst()).get(first.getSecond()); datas.get(first.getFirst()).set(first.getSecond(), datas.get(second.getFirst()).get(second.getSecond())); datas.get(second.getFirst()).set(second.getSecond(), temp); } @Test public void test() { List<List<Double>> datas = new ArrayList<List<Double>>(); List<Double> data1 = new ArrayList<Double>(); data1.add(2d);data1.add(-1d);data1.add(1d);data1.add(1d); datas.add(data1); List<Double> data2 = new ArrayList<Double>(); data2.add(4d);data2.add(1d);data2.add(-1d);data2.add(5d); datas.add(data2); List<Double> data3 = new ArrayList<Double>(); data3.add(1d);data3.add(1d);data3.add(1d);data3.add(0d); datas.add(data3); //进行高斯消元 GaussianEliminationMethod gem = new GaussianEliminationMethod(); gem.forwardElimination(datas); // gem.betterForwardElimination(datas); for(List<Double> data : datas) { System.out.println(data.toString()); } } }
结果集:
时间: 2024-10-10 17:41:00