【算法设计与分析基础】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());
		}
	}
}

  

结果集:

时间: 2024-10-10 17:41:00

【算法设计与分析基础】16、高斯消元法的相关文章

算法设计与分析基础(第3版)读书笔记(及几处翻译上的错误~~)

算法设计与分析基础(第3版) p16 in-place翻译为'在位'?'就地'更合适点 p38 amortized应翻译为'均摊','摊销'这个词简直莫名其妙(可能因为翻译是做算法交易导致的?) p64 迭代优于递归(迭代始终是增量式的,而递归就没办法增量了,除非能够dump整个运行时栈) p73 通过算法可视化得到一个更好的非递归算法(人的图像认知直觉思维?) p79 验证一个拓扑是环.星.还是团?(这个地方有点意思,因为我想到了动态的Verify) p87 凸包问题:从数据结构上讲,Set<

【算法设计与分析基础】大整数乘法

#include<iostream> #include<string> #include<time.h> #include<stdlib.h> #include<sstream> using namespace std; class BigDecimal{ private: int max(int a,int b){//获取两数中的最大值 return a^((a^b) & -(a<b)); } public: string n;

【算法设计与分析基础】关灯游戏

① R.java  用于存储一些全局变量 package lightoff; public class R { /* public static int lightCondition[][] = { {1,0,0,1,1}, {1,0,0,1,1}, {1,0,0,1,1}, {1,0,0,1,1}, }; */ public static int lightCondition[][] = { {1,1,1,1}, {1,1,1,1}, {1,1,1,1}, {1,1,1,1}, }; //灯面

【算法设计与分析基础】19、字符串匹配算法

package cn.xf.algorithm.ch07inputEnhancement; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; /** * * 功能:字符串匹配算法,(还有一种叫KMP算法的,也是很经典的算法,就是比较复杂) * * 第一步:对于给定的长度为m的模式和在模式文本中用到的字母表,按照上面的描述构造移动表 * 第二步:将模式与文本的开

【算法设计与分析基础】20、动态规划-硬币搜集问题

题目: 在n*m格木板中放有一些硬币,每格的硬币数目最多为一个.在木板左上方的一个机器人需要搜集尽可能多的硬币并把他们带到右下方的单元格,每一步,机器人可以从当前的位置向右移动一格 或者向下移动一格,当机器人遇到一个有硬币的单元格的时,就会将这枚硬币搜集起来 解题: 硬币收集的时候,我们 从结果状态开始看,当搜集当前硬币的时候,只有两种方式,从上往下搜集,或者从左向右搜集 也就是当前f[i,j] = max{f[i, j - 1], f[i - 1, j]},初始化第一行和第一列,从第二行和列开

【算法设计与分析基础】17、堆

以数组来存放堆数据 package cn.xf.algorithm.ch06ChangeRule; import java.util.ArrayList; import java.util.List; import org.junit.Test; /** * * 功能:堆的构造 * 1.堆可以定义为一颗二叉树,树的节点包含键,并且满足一下条件 * 1) 树的形状要求:这棵二叉树是基本完备的(完全二叉树),树的每一层都是满的,除了最后一层最右边的元素可能缺位 * 2) 父母优势,堆特性,每一个节点

【算法设计与分析基础】18、霍纳法则

产生随机数 package cn.xf.algorithm.ch02; import java.util.ArrayList; import java.util.List; /** * 生产随机数 * @author xiaof * */ public class Random { /** * 生产一个随机数的数列 * @param n 生成n个数列 * @param m 数据在0和m-1之间 * @param seed 随机初始种子 * @param a 参数 * @param b 参数 *

【算法设计与分析基础】23、堆排序-2

package cn.xf.algorithm.ch09Greedy.util; import java.util.ArrayList; import java.util.List; /** * 堆构造以及排序 * * .功能:堆的构造 * 1.堆可以定义为一颗二叉树,树的节点包含键,并且满足一下条件 * 1) 树的形状要求:这棵二叉树是基本完备的(完全二叉树),树的每一层都是满的,除了最后一层最右边的元素可能缺位 * 2) 父母优势,堆特性,每一个节点的键都要大于或者等于他子女的键(对于任何叶

【算法设计与分析基础】14、快速排序

package cn.xf.algorithm.ch04; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; public class QuikSort { public int hoarePartition(List data, int left, int right) { //当要比对的数据相差为1的时候,表示就只有一条数据要进行比较了 if(d