C语言数据结构——用链表实现两个一元稀疏多项式的合并

代码模板引用自知乎——跟懒猫老师快乐学数据结构。

1. 功能需求

对两个一元稀疏多项式进行加法运算,运算结果按照幂次从高到低依次输出多项式的幂次和系数。


2 .输入输出需求

对两个一元稀疏多项式进行加法运算。

输入形式:

c1 e1 c2 e2...... cn1 en1 ; c1' e1' c2' e2'........cn2' en2'

ci,ci'为整数,分别为两个多项式第i项的系数;ei,ei'为整数,分别为两个多项式第i项的指数,指数乱序排列。

输出形式:

将运算后的结果多项式按幂次降序排列,依次输出结果多项式,结果要求与多项式形态要求一致。

例如:

输入3 5 3 4 -3 0 1 4 0 0为第一个多项式,-3 5 7 1 2 4 3 0 0 0为第二个多项式

输出合并后的多项式:6x^4+7x


3. 总体设计思路

整个程序分为字符串输入系统,多项式链表排序系统,多项式链表合并系统3个部分。

字符串读取系统将读入的字符串数据转化为数值存入链表的结点中。

多项式链表排序系统分别将两个多项式按幂次降序排序。

多项式链表合并系统对两个多项式进行合并。


4.代码实现

#include
#include
#include
typedef struct polynomial
{
    int coef;//系数
    int exp;//指数
    struct polynomial *next;
}*Link,Node;

void inputPoly(Link head);//用于从控制台读入链表的函数
void print(Link head);//打印链表用的函数
bool insert(Link head,int coef,int exp);//向链表插入一个元素的函数
void combin2List(Link heada,Link headb,Link headab);//合并两个链表

int main()
{
    Link headA,headB;//两个多项式的头指针
    Link headAB;//合并后的多项式的头指针

    /*链表的初始化*/
    headA=(Link)malloc(sizeof(Node));
    headA->next=NULL;
    headB=(Link)malloc(sizeof(Node));
    headB->next=NULL;
    headAB=(Link)malloc(sizeof(Node));
    headAB->next=NULL;

    printf("请输入第一个多项式的系数和指数,以(0 0)结束:\n");
    inputPoly(headA);
    printf("第一个");
    print(headA);
    printf("请输入第二个多项式的系数和指数,以(0 0)结束:\n");
    inputPoly(headB);
    printf("第二个");
    print(headB);

    combin2List(headA,headB,headAB);
    printf("合并后");
    print(headAB);
    return 0;
}

/**输入二项式数据的函数*/
/*这个函数用来输入二项式,给用户合适的提示,读入用户输入的系数和指数。
调用函数insert,将用户输入的二项式的一项插入到链表中去。*/
void inputPoly(Link head)
{
    int coef,exp;//系数和指数
    printf("请输入系数和指数(如:\"2 3\"表示2x^3):");
    scanf("%d %d",&coef,&exp);
    while(coef!=0||exp!=0)//连续输入多个系数和指数
    {
        insert(head,coef,exp);//调函数输入多项式
        printf("请输入系数和指数:");
        scanf("%d %d",&coef,&exp);
    }
}

/*向多项式链表中插入元素的函数*/
bool insert(Link head,int coef,int exp)
{
    Link node;  //node指针指向新创建的节点
    Link q,p;  
    q = head;
    p = head->next;
    node = (Link)malloc(sizeof(Node));//创建一个新结点
    if(head->next==NULL)//空表,插第1个
    {
        node->coef = coef;
        node->exp = exp;
        head->next = node;
        node->next = NULL;
    }
    else
    {
        while(p != NULL)//循环访问链表中的所有节点
	    { 
            node->coef = coef;
            node->exp = exp;
            //如果node节点的指数比p节点的指数大,则插在p的前面,完成插入后,提前退出
            if(node->exp > p->exp)
            {
            	node->next = p;
            	q->next = node;
            	return 1;
			}
            //如果node节点的指数和p节点的指数相等,则合并这个多项式节点,提前退出
            else if(node->exp == p->exp)
            {
            	p->coef += node->coef;
            	return 1;
			}
            //如果node节点的指数比p节点的指数小,继续向后移动指针
            else
            {
            	q = p;
            	p = p->next;
			}
	    }
	    //如果退出循环是当前指针p移动到链表结尾,则说明之前没有插入,那么当前node节点的指数值是最大值,此时插在链表的最后面
	    node->exp = exp;
	    node->coef = coef;
	    q->next = node;
	    node->next = NULL;
    }
    return true;
}

/*打印多项式链表的函数*/
/*
① 通过指针访问链表
② 多重条件语句嵌套
③ 数字转换为字符串函数itoa
④ 标志是否为第一个节点的flag的设置
⑤ 字符串连接函数strcat
⑥ 字符串清空函数memset。memset(item,0,20);清空长20的字符串item
*/
void print(Link head)
{
    Link p; //指向链表要输出的结点
    printf("多项式如下:\n");
    p=head->next;

    if (p == NULL)
    {
        printf("多项式为空\n");
        return;
    }
    // 不是空表
    char item[20]="";//要打印的当前多项式的一项
    char number[7]="";//暂时存放系数转换成的字符串

    bool isFirstItem=true;//标志是否为第一个节点的flag
    //打印节点
    while(p != NULL)
    {
        if(isFirstItem) //如果是第一项,不要打+号
        {
        	isFirstItem = false;
			if(p->coef > 0)
        	{
			    if(p->coef !=1){
			        if(p->exp == 1) printf("%dx",p->coef);
        	        printf("%dx^%d",p->coef,p->exp);}
        	    else{
        	        if(p->exp == 1) printf("x");
        	        printf("x^%d",p->exp);}//如果系数为1,不用打系数
            }
        	else if(p->coef < 0)//如果系数为负数,系数自身带有符号
			{
			    if(p->coef != -1){
			        if(p->exp == 1) printf("%dx",p->coef);
        	        printf("%dx^%d",p->coef,p->exp);}
        	    else{
        	        if(p->exp == 1) printf("-x");
        	        printf("-x^%d",p->exp);}//系数为-1打印负号
            }  
			else
			    printf(""); 
		}
		
		else if(!isFirstItem && p->exp == 0)//如果指数为0,直接打系数不用打x^和指数
		{
			if(p->coef > 0)1
			    printf("+%d",p->coef);
			else if(p->coef <0)
			    printf("%d",p->coef);
		    else
			    printf("");    
		}
		
		else if(!isFirstItem&& p->exp == 1)//如果指数为1,不打指数,否则打指数
        {
        	if(p->coef > 0)
        	{
			    if(p->coef !=1)
        	        printf("+%dx",p->coef);
        	    else
        	        printf("+x");//如果系数为1,不用打系数
            }
        	else if(p->coef < 0)//如果系数为负数,系数自身带有符号
			{
			    if(p->coef != -1)
        	        printf("%dx",p->coef);
        	    else
        	        printf("-x");//系数为-1打印负号
            }  
			else
			    printf("");    
		}
		
        else if(!isFirstItem && p->exp != 0 && p->exp != 1)//如果不是第一项,且系数为正数,要打加号 
        {
        	if(p->coef > 0)
        	{
			    if(p->coef !=1)
        	        printf("+%dx^%d",p->coef,p->exp);
        	    else
        	        printf("+x^%d",p->exp);//如果系数为1,不用打系数
            }
        	else if(p->coef < 0)//如果系数为负数,系数自身带有符号
			{
			    if(p->coef != -1)
        	        printf("%dx^%d",p->coef,p->exp);
        	    else
        	        printf("-x^%d",p->exp);//系数为-1打印负号
            }  
			else
			    printf("");    
		}
		p = p->next;
    }
    printf("\n");
    return;
}

/*合并两个有序链表a,b到链表ab;heada.headb,headab分别为链表a,b,ab的头指针*/
void combin2List(Link heada,Link headb,Link headab)
{
    Link pa,pb,pab;//指向a,b链表和ab的指针
    pa=heada->next;
    pb=headb->next;
    pab=headab->next;

    while(pa!=NULL&&pb!=NULL)//a,b链表都没有没有访问完毕
    {
        //如果指数a>指数b,a节点插入ab链表,a指针后移
        if(pa->exp > pb->exp)
        {
            insert(headab,pa->coef,pa->exp);
            pa = pa->next;
		}
        //如果指数a<指数b,b节点插入ab链表,b指针后移
        else if(pa->exp < pb->exp)
        {
        	insert(headab,pb->coef,pb->exp);
        	pb = pb->next;
		}
        //如果指数a==指数b,a、b系数相加,插入ab链表,a、b指针后移
        else if(pa->exp == pb->exp)
        {
        	pa->coef += pb->coef;
        	insert(headab,pa->coef,pa->exp);
        	pa = pa->next;
        	pb = pb->next;
		}
    }
     //如果a、b链表还有尾巴,将它加到ab链表后面
    while(pa!=NULL)
    {
        insert(headab,pa->coef,pa->exp);
        pa = pa->next;
    }
    while(pb!=NULL)
    {
        insert(headab,pb->coef,pb->exp);
        pb = pb->next;        
    }
    return;
}


你可能感兴趣的:(链表,数据结构,c语言)