【数据结构_浙江大学MOOC】第二讲 线性结构

lickylin 2019-06-28

函数题给出编译器为 C(gcc) 的解答,编程题给出编译器 C++(g++)Python(python3) 的解答。


函数题

两个有序链表序列的合并

题目

函数接口定义:

List Merge( List L1, List L2 );

其中List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

L1L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

裁判测试程序样例:

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

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

输入样例:

3
1 3 5
5
2 4 6 8 10

输出样例:

1 2 3 4 5 6 8 10 
NULL
NULL

解读题目

题目中有两句话:
1、L1L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1L2合并为一个非递减的整数序列。

这里也说明了我们只需要写一个函数Merge。实现思路为比较链表 L1 和 L2,然后以非递减的形式输出到一个新链表 L 上,最后返回链表 L。

2、应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

第二句话中的“直接使用原序列中的结点”其实是要求我们把原链表上的结点一个一个摘下来,挂到新链表上。

实现代码

List Merge( List L1, List L2 ){
  List p1, p2, p3, L;
  // 用malloc函数申请结构
  L = (List)malloc(sizeof(struct Node));
  p1 = L1->Next;
  p2 = L2->Next;
  p3 = L;
  // 通过循环来遍历一遍,比较L1和L2,将值小的依次加到p3
  // 循环条件为 P1!=NULL && p2!=NULL
  while(p1 && p2){
    if(p1->Data <= p2->Data){
      //把结果拷贝过去
      p3->Next = p1;
      p3 = p1;
      // p1指针向后移一位
      p1 = p1->Next;
    }else{
      p3->Next = p2;
      p3 = p2;
      p2 = p2->Next;
    }
  }
  //将未处理完的另一个链表的结点复制过去
  p3->Next = p1? p1 : p2;
  L1->Next = NULL;
  L2->Next = NULL;
  return L;
}

提交结果

【数据结构_浙江大学MOOC】第二讲 线性结构

编程题

一元多项式的乘法与加法运算

题目

设计函数分别求两个一元多项式的乘积与和。

输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0

输入样例:

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

解读题目

首先我们看输入样例,其实表示了两个多项式。第一个多项式非零项有 4 项:$3x^4-5x^2+6x-2$,第二哥多项式非零项有 3 项:$5x^{20}-7x^4+3x$。

要求分别计算两个多项式的乘积与和,输出第一项为乘积的系数和指数,第二行为和的系数和指数。

求解思路从以下几个方面考虑:

  • 多项式表示

表示多项式的关键信息,即非零项。有两种表示方法:数组和链表。根据它们二者的特点,在这道题里项数是已知的,有一种比较好的实现方法叫动态数组

选定了表示方法后,考虑数据结构设计。

选择链表在设计数据结构的时候有系数、指数、和指针(结构指针)。

  • 程序框架

程序框架搭建的大致流程如下:

int main(){
    读入多项式1
    读入多项式2
    乘法运算并输出
    加法运算并输出
    
    return 0;
}

实现以下四步:

  • 读一个多项式
  • 两个多项式相乘
  • 两个多项式相加
  • 多项式输出

实现代码

C++ 版本

#include <iostream>
#include <vector>
using namespace std;

#define Max_Expon 1001
#define Max_Mul_Expon 1000001

int main(int argc, const char * argv[])
{
    //输入
    vector<int > Polynomial_1(Max_Expon, 0);
    vector<int > Polynomial_2(Max_Expon, 0);
    int coef = 0;
    int expon = 0;
    int num = 0;

    cin>>num;
    for(int i=0; i<num; ++i)
    {
        cin>>coef>>expon;
        Polynomial_1[expon] = coef;
    }

    cin>>num;
    for (int i=0; i<num; ++i)
    {
        cin>>coef>>expon;
        Polynomial_2[expon]=coef;
    }

    //进行计算
    vector<int> Polynomial_Result_Mul(Max_Mul_Expon,0);
    vector<int> Polynomial_Result_Add(Max_Expon,0);

    for (int i=0; i<Polynomial_1.size(); ++i)
    {
        for (int k=0;k<Polynomial_2.size(); ++k)
        {
            Polynomial_Result_Mul[i+k]+=Polynomial_1[i]*Polynomial_2[k];
        }
    }

    for (int i=0; i<Max_Expon; ++i)
    {
        Polynomial_Result_Add[i]=Polynomial_1[i]+Polynomial_2[i];
    }

    //输出
    int flag_1=0,flag_2=0;
    for (int i=Max_Mul_Expon-1; i>=0; i--)
    {
        if (Polynomial_Result_Mul[i]!=0)
        {
            if (flag_1==0)
            {
                flag_1=1;
                cout<<Polynomial_Result_Mul[i]<<' '<<i;
            } else
            {
                cout<<' '<<Polynomial_Result_Mul[i]<<' '<<i;
            }
        }
    }

    if(flag_1==0)
    {
        cout<<"0 0";
    }
    cout<<endl;

    for (int i = Max_Expon-1; i >=0; i--)
    {
        if(Polynomial_Result_Add[i]!=0)
        {
            if(flag_2==0)
            {
                flag_2=1;
                cout<<Polynomial_Result_Add[i]<<''<<i;
            }else
            {
                cout<<' '<<Polynomial_Result_Add[i]<<' '<<i;
            }
        }
    }

    if(flag_2==0)
    {
        cout<<"0 0";
    }

    return 0;
    
}

提交结果:

【数据结构_浙江大学MOOC】第二讲 线性结构

Python3 版本

p= {}

def mysplit(s, split = ' '):
    l = []
    for i in s:
        if i == split:
            num = s[ : s.index(i)]
            if len(num) != 0:
                l.append(num)
            s = s[s.index(i)+1 : ]
            
    l.append(s)         
    return l

# 输入
for i in range(2):
    s = input()
    l = mysplit(s)
    n = int(l.pop(0))
    p[i+1] = {}
    for j in range(n):
        p[i+1][int(l[j*2+1])] =int(l[j*2])

# 多项式相乘
p['*'] = {}
for i in p[1]:
    for j in p[2]:
        if p['*'].get(i+j):
            p['*'][i+j] += p[1][i] * p[2][j]
        else:
            p['*'][i+j] = p[1][i] * p[2][j]

# 多项式相加
p['+'] ={}
p['+'] = p[1]
for j in p[2]:
    if p['+'].get(j):
        p['+'][j] += p[2][j]
    else:
        p['+'][j] = p[2][j]

# 处理多项式为空的情况
def zero(p):
    for i in p:
        if p[i] != 0:
            return
    p.clear()
    p[0] = 0

zero(p['*'])
zero(p['+'])

# 输出
def pprint(p):
    for i in sorted(p, reverse = True):
        e = ' '
        if(i  == sorted(p, reverse = True)[-1]):
            e = ''

        print(p[i], i, end = e)

pprint(p['*'])
print('')
pprint(p['+'])

提交结果

【数据结构_浙江大学MOOC】第二讲 线性结构


参考链接:

视频编程作业-两个有序列表的合并
两个有序链表序列的合并(15 分)
02-线性结构1 一元多项式的乘法与加法运算 (20分)
一元多项式的乘法与加法运算(20 分)
数据结构2.1-一元多项式的乘法与加法运算

不足之处,欢迎指正。

$$$$

相关推荐