zoukankan      html  css  js  c++  java
  • 【算法设计与分析基础】16、高斯消元法

    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());
    		}
    	}
    }
    

      

    结果集:

  • 相关阅读:
    QT 双缓冲
    ubuntu 安装SVN客户端
    高并发linux内核网络参数调优
    c aes 解密
    qt 字符类型转换
    c++ ado 操作类
    Qt中将QString转换为char *或者相反
    c++ aes 加密 解密
    [转载]python编码转换遇到的非法字符的解决方法
    [转载] python异常如何全面捕获
  • 原文地址:https://www.cnblogs.com/cutter-point/p/7113457.html
Copyright © 2011-2022 走看看