1. 程式人生 > >java實現多項式的加減乘除

java實現多項式的加減乘除

package polynomial;


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

package polynomial;

// import java.util.InputMismatchException;
import java.util.Scanner;

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