数据结构(暑假篇7.20)

本文介绍了链表合并及多项式的基本运算实现方法,包括两个有序链表的合并、一元多项式的乘法与加法运算,以及链表的逆序处理等。详细解析了算法流程,分享了调试过程中遇到的问题及解决思路。

线性结构1 两个有序链表序列的合并

题目已给代码:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType Data;
    PtrToNode   Next;
};
typedef PtrToNode List;

List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表;空链表将输出NULL */

List Merge( List L1, List L2 );

int main()
{
    List L1, L2, L;
    L1 = Read();
    L2 = Read();
    L = Merge(L1, L2);
    Print(L);
    Print(L1);
    Print(L2);
    return 0;
}

/* 你的代码将被嵌在这里 */

函数代码:

List Merge(List L1,List L2)
{
 List P,rear,t1,t2;
 P=(List)malloc(sizeof(struct Node));//PTA提交时要加struct,否则无法通过 
 rear=P;
 t1=L1->Next;//L1,L2带头结点 
 t2=L2->Next;
 while(t1&&t2)
 {
   if(t1->Data<=t2->Data)
  {
   rear->Next=t1;
   rear=t1;
   t1=t1->Next;
  }
  else if(t1->Data>t2->Data)
  {
   rear->Next=t2;
   rear=t2;
   t2=t2->Next;
     }
  
 }
  rear->Next=t1?t1:t2;
  L1->Next=NULL;
  L2->Next=NULL;
  return P;
}

首先要注意L1,L2还有合并后的链表L都是带头结点的单链表,这就意味着t1,t2开始分别要指向L1,L2的下一个结点,因为空结点Data项是空的。同时Merge()函数内新建链表的头结点不需要删除。审题真的很重要!!!
另外,题目中已说明直接使用原序列中的结点,这就意味着除了头结点需要建立外,不需要建立其他结点,直接从头结点开始依次指向符合条件的t1,t2。注意合并为一个非递减的整数序列。
当t1,t2其中一方为空时,直接将rear->Next赋给不为空的一项即可。(如t1已为空,t2还有剩余项时,此时的t2已经移动到了剩余项中的首项,直接rear->Next=t2,即可完成剩余所有项的合并。)
合并完成后,L1,L2中的输出应为NULL,即完成合并后将L1,L2的头结点置空,为L1->Next=NULL;L2->Next=NULL
还有一点P=(List)malloc(sizeof(struct Node))这条语句中的struct在Dev-C++中可以编译通过,而在PTA却不可以,所以…以后还是写全吧。

线性结构2 一元多项式的乘法与加法运算

#include<iostream>
#include<malloc.h>
using namespace std;
typedef struct PolyNode *Polynomial;
struct PolyNode
{
 int coef;
 int expon;
 Polynomial link;
};
void Attach(int c,int e,Polynomial *prear)
{
 Polynomial P;
 P=(Polynomial)malloc(sizeof(struct PolyNode));
 P->coef=c;//对新结点赋值 
 P->expon=e;
 P->link=NULL;
 (*prear)->link=P;
 *prear=P; //修改prear的值 
}

Polynomial ReadPoly()
{
 Polynomial P,rear,t;
 int n,c,e;
 P=(Polynomial)malloc(sizeof(struct PolyNode));//链表头空结点 
 P->link=NULL; 
 rear=P;
 scanf("%d",&n);
 while(n--)
 {
   scanf("%d%d",&c,&e);
  Attach(c,e,&rear);//将当前项插入多项式尾部 
 }
 t=P;
 P=P->link;
 free(t);//删除临时生成的空结点 
 return P;
}

Polynomial Add(Polynomial P1,Polynomial P2)
{
 Polynomial P,t,rear,t1,t2;
 int sum;
 P=(Polynomial)malloc(sizeof(struct PolyNode));
 P->link=NULL;
 rear=P;
 t1=P1;
 t2=P2;
 while(t1&&t2)
  {
  if(t1->expon>t2->expon)
  {
   Attach(t1->coef,t1->expon,&rear);
   t1=t1->link; 
  }
  else if(t1->expon<t2->expon)
  {
   Attach(t2->coef,t2->expon,&rear);
   t2=t2->link;
     }
  else 
  {
   int sum=t1->coef+t2->coef;
   if(sum)
   {
    Attach(sum,t1->expon,&rear);
   }
   t1=t1->link;
   t2=t2->link;
     }
 }

 for(;t1;t1=t1->link)Attach(t1->coef,t1->expon,&rear);//while(t1)  {Attach(t1->coef,t1->expon,&rear); t1=t1->link;  }
 for(;t2;t2=t2->link)Attach(t2->coef,t2->expon,&rear);// while(t2) {Attach(t2->coef,t2->expon,&rear); t2=t2->link;  }  
 t=P;
 P=P->link;
 rear->link=NULL;
 free(t);
 return P;
}

Polynomial Mult(Polynomial P1,Polynomial P2)
{
 Polynomial P,rear,t,t1,t2;
 int c,e;
 if(!P1||!P2) return NULL;
 P=(Polynomial)malloc(sizeof(struct PolyNode));
 P->link=NULL;
 rear=P;
 t1=P1;
 t2=P2;
  while(t2)//先用P1的第一项乘以P2,得到P 
 {
  Attach(t1->coef*t2->coef,t1->expon+t2->expon,&rear);
  t2=t2->link;
 }
 t1=t1->link;
 while(t1)
 {
  t2=P2;
  rear=P;
    while(t2)
  {
    e=t1->expon+t2->expon;
    c=t1->coef*t2->coef;
   while(rear->link&&rear->link->expon>e)
   rear=rear->link;
   if(rear->link&&rear->link->expon==e)
   {
    if(rear->link->coef+c)
        {
     rear->link->coef+=c;
    }
    else 
    {
     t=rear->link;
     rear->link=t->link;
     free(t);
         }
   }
      else 
   {
    t=(Polynomial)malloc(sizeof(struct PolyNode));
    t->coef=c;
    t->expon=e;
    t->link=rear->link;
    rear->link=t;
    rear=rear->link;
   }
        t2=t2->link;
  }
  t1=t1->link;
 }
 t2=P;
 P=P->link;
 free(t2);
 return P;
}

void PrintPoly(Polynomial P)
{//输出多项式 
 int flag=0;//辅助调整输出格式用 
 if(!P)
 {
   printf("0 0\n");
   return ; 
 }
 while(P)
 {
   if(!flag)
  flag=1;
  else 
  printf(" ");
  printf("%d %d",P->coef,P->expon);
  P=P->link;
 }
 printf("\n");
}
int main()
{
 Polynomial P1,P2,PP,PS;
 P1=ReadPoly();
 P2=ReadPoly();
 PP=Mult(P1,P2);
 PrintPoly(PP); 
 PS=Add(P1,P2);
 PrintPoly(PS); 
} 

算是现阶段写的最长的代码了吧…因为出错运行的时候电脑死机了两次,苦笑…
for(;t1;t1=t1->link)Attach(t1->coef,t1->expon,&rear);
for(;t2;t2=t2->link)Attach(t2->coef,t2->expon,&rear);
Add()函数中的这两条语句就是让我死机的罪魁祸首,因为写的是
for(;t1;t1->link)Attach(t1->coef,t1->expon,&rear);
for(;t2;t2->link)Attach(t2->coef,t2->expon,&rear);
但是我很好奇为什么这种错误的写法当指数不为0时仍能通过,并且在PTA的测试中不完全错误。之后还要仔细分析分析。

错误方式在PTA中上传的结果
乘法部分让我头疼了好一会儿,一开始没有搞清楚t2和rear的用途,结果导致应该为rear的地方全部写成了t2…rear是为了将新链表从头到尾和新产生结果的系数进行比较,完成插入,合并或删除(新结点与刚开始链表对应结点的指数相同,系数相反)操作,t2是与t1完成系数相乘,指数相加操作。
此题中乘法和加法最初都建立了一个空结点便于操作,最后
需释放此空结点。
PrintPoly()函数中flag设置的也很巧妙,可以避开第一个多打的空格。

线性结构3 Reversing Linked List

#include<iostream>
#include<algorithm>
using namespace std;
#define MAXSIZE 100010
struct node
{
 int Data;
 int Next;
}node[MAXSIZE];
int main()
{
 int first,n,k;
 scanf("%d%d%d",&first,&n,&k);
 for(int i=0;i<n;i++)
 {
  int Address,Data,Next;
  scanf("%d%d%d",&Address,&Data,&Next);
  node[Address].Data=Data;
  node[Address].Next=Next;
 }
  int List[MAXSIZE];
 int x=first;
 int j=0;
 while(x!=-1)
 {
  List[j]=x;
  x=node[x].Next;
  j++;
 }
  int i=0;
 while(i+k<=j)
 {
  reverse(&List[i],&List[i+k]);
  i=i+k;
 }
 int m;
  for(m=0;m<j-1;m++)
 printf("%05d %d %05d\n",List[m],node[List[m]].Data,List[m+1]);
 printf("%05d %d -1\n",List[m],node[List[m]].Data);
}

这题参考了Kunaly大佬的代码,不得不说建立结构数组node[MAXSIZE]和数组List[MAXSIZE]并将其联系起来,这个idea真的很妙。
将node[]的数组下标存储为当前元素的地址,Data,Next分别记为数据和下一项的地址。
使用List[]数组记录从1到n对应的地址,然后使用reverse()函数将相应的位置进行逆转,输出时需特别注意输出的最后一个元素要单独列出来,因为它的Next永远都是-1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值