菜单

多项式加法

duckflew
发布于 2020-10-20 / 196 阅读
0
0

多项式加法

多项式加法

public class Polynomial {
	Polynomial next;
	 double data; // 系数值
	 int power; // 幂值
	 public Polynomial(){
		 this(0.0, -1);
	 }
	 
	 public Polynomial(double data, int power){
		 this.data = data;
		 this.power = power;
		 this.next = null;
	 }
	 
	 public Polynomial(double data, int power, Polynomial next){
		 this.data = data;
		 this.power = power;
		 this.next = next;
	 }
	 
	 public String toString(){
		 return "data = "+data+",power = "+power;
	 }
}
public class Util 
{
	// Polynomial p;
	Scanner input = new Scanner(System.in);
	public Util()
	{
		// p = new Polynomial(); 
	}
	
	/**
	 * 1. 判断多项式中是否存在该幂数的项数 
	 * @param power 幂数
	 * @param p 链表
	 * @return 是否存在power相同的项数
	 * 
	 * complete
	 */
	private boolean locateElem(int power, Polynomial p)
	{
		Polynomial current = p.next;
		/*         // 不需要判断power是否小于0
 		if(power<0)
			return false;
		*/
		while(current!=null)
		{
			if(current.power == power)
				return true;
			current = current.next;
		}
		return false;
	}
	
	
	/**
	 * 2.做相加的操作
	 * @param data
	 * @param power
	 * @param current
	 * @param previous
	 * @return
	 */
	private boolean addElem(double data, int power, Polynomial current, Polynomial previous)
	{
		if(power == current.power)
		{
			current.data = current.data + data;
			if(0 == current.data && previous != null)
				previous.next = current.next;
			if(0 == current.data && previous == null)
				current = current.next;
			return true;
		}
 
		return false;
	}
	private void addAllElem(double data, int power, Polynomial p)
	{
		Polynomial current;
		Polynomial previous;
		current = p;
		previous = p;
		while(current!=null && power!=current.power)
		{
			previous = current;
			current = current.next;
		}
		current.data = current.data + data;
		if(0 == current.data && current!=previous) // 当current的next为0的时候和current为头节点
			previous.next = current.next;
		else
			p = current.next;
	}
	
	private boolean subElem(double data, int power, Polynomial current, Polynomial previous)
	{
		if(power == current.power)
		{
			current.data = current.data - data;
			if(0 == current.data && previous != null)
				previous.next = current.next;
			else
				current = current.next;
			return true;
		}
 
		return false;
	}
	
	// 4. 多项式的相乘操作  这里的p应该存放的是b中的多项式节点
	private void mulElem(double data1, int power1, double data2, int power2, Polynomial p) 
	{
		p.data = data1*data2;
		p.power = power1+power2;
	}
	
	
	/** 5. 在不存在相同幂数的情况下进行插入的操作
	 * 特殊的插入 可以在链表只有头结点的时候在第一个位置进行插入
	 * @param data
	 * @param power
	 * @param p
	 * @return
	 * 
	 * complete
	 */
	private boolean insertElem(double data, int power, Polynomial p)
	{
		Polynomial current;
		Polynomial temp = new Polynomial(data, power, null);
		Polynomial previous;
		current = p;
		// 1.首先判断不存在首元节点的情况
		if(current.next == null)
		{
			current.next = temp;
			return true;
		}
		previous = p;
		current = p.next;	
		while( current!=null && current.power<power)
		{
			previous = current;
			current = current.next;
		}
		previous.next = temp;
		temp.next=current;
		return true;
			
	}
	
 
	/**
	 * 6. 比较当前两个节点谁的power更大  前者大返回 1; 后者大返回-1;一样大返回0;
	 * 
	 * @param a 链表的一个节点
	 * @param b 链表的一个节点
	 * @return 1、0或者-1
	 * 
	 * complete
	 */
	private int getCurElem(Polynomial a, Polynomial b)
	{
		if( a.power>b.power )
			return 1;
		else if( a.power<b.power )
			return -1;
		else 
			return 0;
		
	}
	
	
	// -----------------------------------
 
	 
 
	/**
	 *  1. 输入m项的data和power建立一元多项式
	 * @param m
	 * @param p
	 * 
	 * complete
	 */
	public void createPolyn(int m, Polynomial p)
	{
		double data;
		int power;
		// 正序
		for(int i=0; i<m; i++)
		{
	
			System.out.print("请输入第"+(i+1)+"系数:");
			data = input.nextDouble();
 
			if( 0==data )
			{
				System.out.println("系数不能为0");
				continue;
			}
			System.out.print("请输入第"+(i+1)+"幂数:");
			power = input.nextInt();
			
			if(locateElem(power, p)) // 如果存在power相同的
			{
				addAllElem(data, power, p);
			}
			else
			{
				insertElem(data, power, p);
			}
		
			
		}
	}
	
	
	/**
	 * 2. 销毁一元多项式
	 * @param p
	 * 
	 * complete
	 */
	public void destroyPolyn(Polynomial p)
	{
		p.next = null;
		p = null;
	}
	
	
	/**
	 * 3. 打印输出一元多项式
	 * @param p
	 * 
	 * complete
	 */
	public void printPolyn(Polynomial p)
	{
		Polynomial current;
		current = p.next;
		int count = 0;
		while(current!=null)
		{
			if( current.data>0 )
			{
				if(0 == count)
				{
					System.out.print(current.data+"x^"+current.power);
					count++;
				}
				else
				{
					System.out.print("+"+current.data+"x^"+current.power);
				}
			}	
			if( current.data<0 )
			{
				if(0 == count)
				{
					System.out.print(current.data+"x^"+current.power);
					count++;
				}
				else
				{
					System.out.print(current.data+"x^"+current.power);
				}
			}	
			current = current.next;
		}
		System.out.println();
	}
	
	
	/**
	 * 4. 返回一元多项式的项数 
	 * @param p
	 * @return
	 * 
	 * complete
	 */
	public int polynLength(Polynomial p)
	{
		Polynomial current = p.next;
		int count = 0;
		while(current!=null)
		{
			count++;
			current = current.next;
		}
		return count;
	}
	/*
	 * Polynomial a = ...;
	 * h = a;
	 * 后面修改h  a中会改变
	 * 
	 * Polynomial a = ...;
	 * h = a;
	 * 后面修改a  h中会改变
	 * 
	 * 在计算力不够的时候,牢记引用变量的名字都代表地址,地址直接操作的改变
	 * 会对所有指向这个地址的引用类型的变量都造成修改。
	 * 引用类型变量(名字)的值可以修改(修改装的对象:即地址)
	 * 
	 */
	/**
	 * 
	 * @param a
	 * @param b
	 * 
	 * complete
	 */
	public void addPolyn(Polynomial a, Polynomial b)
	{
		Polynomial currenta = a.next;
		Polynomial currentb = b.next;
		Polynomial previousa = a;  // 保存a的前驱
		/*
		 * 在将当前(currentb)插入到a链表中之后
		 * 当前的currentb中的后继就被链接到了a链表之后了
		 * 所以在操作currentb之前我们需要将currentb的后继存储到一个后继节点对象中去
		 * 在每次循环的时候,再将后继(subsequenctb)赋给currentb
		 * */
		Polynomial subsequentb = currentb.next;
		while(currentb != null)
		{
			if(getCurElem(currenta, currentb)<0) // 如果currenta小于当前的currentb
			{
				// 将currenta移向next
				previousa = currenta;
				currenta = currenta.next;
				/*
				 * 当currenta.next为空的时候,说明currentb比currenta中的所有元素都要大
				 * 将currentb插入到currenta的后面
				 */
				// if(getCurElem(currenta, currentb)>0)  continue;
				// 当currenta.next 为null 但是currenta大于currentb的时候
				
				if(currenta.next == null && getCurElem(currenta, currentb)<0) // 在a的最后一个元素都比b的第一个元素小的时候
				{
					insertElem(currentb.data, currentb.power, currenta);
					currentb = currentb.next;
					currentb = subsequentb; // 插入之后currentb本身没有从链表上断开
					if(currentb!=null)
					{
						subsequentb = currentb.next;
					}
					
						
				}
				// 第一次currenta移向next的操作结束之后,currenta依旧可能比currentb小
			}
			/*
			 * 这里的currenta大于currentb处于刚好的临界条件
			 * 所以必然此刻的currentb处于previousa和currenta之间
			 */
			
			else if(getCurElem(currenta, currentb)>0) // 如果currenta大于当前的currentb
			{
				/*
				 * 将currentb连接到previousa和currenta之间
				 */
				previousa.next = currentb; 
				currentb.next = currenta;  
				
				/*
				 * 因为已经将currentb插入到了previousa和currenta之间了
				 * 所以此刻的previousa不是等于currenta 应该等于此刻的currentb
				 * 
				 * 最后将currentb的指向重新赋值为b的后继 subsequentb
				 */
				previousa = currentb;
				currentb = subsequentb;
				// 做currentb的后继的赋值的操作必须先判断currentb是否为空,为空的话取后继为造成空指针
				if(currentb != null) 
					subsequentb = currentb.next;	
			}
			else
			{
				addElem(currentb.data, currentb.power, currenta, previousa);
				currentb = currentb.next;
			}
		}
		b.next = null;
	}// 5. 将两个一元多项式相加 Pa = Pa + Pb; 并且销毁Pb
	
	public void subPolyn(Polynomial a, Polynomial b)
	{
		Polynomial currenta = a.next;
		Polynomial currentb = b.next;
		Polynomial previousa = a;  // 保存a的前驱
		/*
		 * 在将当前(currentb)插入到a链表中之后
		 * 当前的currentb中的后继就被链接到了a链表之后了
		 * 所以在操作currentb之前我们需要将currentb的后继存储到一个后继节点对象中去
		 * 在每次循环的时候,再将后继(subsequenctb)赋给currentb
		 * */
		Polynomial subsequentb = currentb.next;
		while(currentb != null)
		{
			if(getCurElem(currenta, currentb)<0) // 如果currenta小于当前的currentb
			{
				// 将currenta移向next
				previousa = currenta;
				currenta = currenta.next;
				/*
				 * 当currenta.next为空的时候,说明currentb比currenta中的所有元素都要大
				 * 将currentb插入到currenta的后面
				 */
				// if(getCurElem(currenta, currentb)>0)  continue;
				// 当currenta.next 为null 但是currenta大于currentb的时候
				
				if(currenta.next == null && getCurElem(currenta, currentb)<0) // 在a的最后一个元素都比b的第一个元素小的时候
				{
					insertElem(-currentb.data, currentb.power, currenta);
					currentb = currentb.next;
					currentb = subsequentb; // 插入之后currentb本身没有从链表上断开
					if(currentb!=null)
					{
						subsequentb = currentb.next;
					}
					
						
				}
				// 第一次currenta移向next的操作结束之后,currenta依旧可能比currentb小
			}
			/*
			 * 这里的currenta大于currentb处于刚好的临界条件
			 * 所以必然此刻的currentb处于previousa和currenta之间
			 */
			
			else if(getCurElem(currenta, currentb)>0) // 如果currenta大于当前的currentb
			{
				/*
				 * 将currentb连接到previousa和currenta之间
				 */
				currentb.data = -currentb.data;
				previousa.next = currentb; 
				currentb.next = currenta;  
				
				/*
				 * 因为已经将currentb插入到了previousa和currenta之间了
				 * 所以此刻的previousa不是等于currenta 应该等于此刻的currentb
				 * 
				 * 最后将currentb的指向重新赋值为b的后继 subsequentb
				 */
				previousa = currentb;
				currentb = subsequentb;
				// 做currentb的后继的赋值的操作必须先判断currentb是否为空,为空的话取后继为造成空指针
				if(currentb != null) 
					subsequentb = currentb.next;	
			}
			else
			{
				subElem(currentb.data, currentb.power, currenta, previousa);
				currentb = currentb.next;
			}
		}
		b.next = null;
		
	}// 6. 将两个一元多项式相减 Pa = Pa - Pb; 并且销毁Pb
	/*
		Polynomial a 引用类型的变量相当于C语言中的指针,a代表的是对应的地址
		a的地址不能被修改,只能修改a对应的地址的值, 所以下面的a被我们修改了
		所以必须重新返回一个Polynomial类型的a。
	*/
	// public Polynomial multiplyPolyn(Polynomial a, Polynomial b)
	public void multiplyPolyn(Polynomial a, Polynomial b)
	{
		Polynomial currenta = a.next;
		Polynomial currentb = b.next;
		Polynomial current = new Polynomial();
		
		Polynomial subsequentb = currentb.next;
		Polynomial temp = new Polynomial(); 
		temp = current;
		a.next = null;
		while(currenta != null)
		{
			while(currentb != null)
			{
				current.next = new Polynomial();
				mulElem(currenta.data, currenta.power, currentb.data, currentb.power, current.next);
				currentb = currentb.next;
				current = current.next;
			}
			currentb = subsequentb;
			currenta = currenta.next;
			if(currentb != null)
				subsequentb = subsequentb.next;
		}
		/*
		a = temp;	
		temp = null;
		b.next = null;
		return a;
		*/
		
		temp = temp.next;
		a.next = temp;
		b.next = null; // b也不能直接被修改,b也相当于指针
	}// 7. 将两个一元多项式相乘 Pa = Pa * Pb; 并且销毁Pb
}

package polynomial;
 
public class Test {
	public static void main(String[] args) {
		Util u = new Util();
		/*
		Polynomial p = new Polynomial();
		u.createPolyn(3,p);
		System.out.println(u.polynLength(p));
		u.printPolyn(p);
		u.destroyPolyn(p);
		u.printPolyn(p);
		*/
		Polynomial a = new Polynomial();
		u.createPolyn(3, a);
 
		Polynomial b = new Polynomial();
		u.createPolyn(3, b);
 
		// u.addPolyn(a, b);
		// u.subPolyn(a, b);
		u.multiplyPolyn(a, b);
		u.printPolyn(a);
		// u.printPolyn(b);
		
	}
}

评论