1. 程式人生 > >【算法設計與分析基礎】16、高斯消元法

【算法設計與分析基礎】16、高斯消元法

ane sys cnblogs 根據 gauss tostring logs junit air

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

  

結果集:

技術分享

技術分享

【算法設計與分析基礎】16、高斯消元法