线性表的应用:求两个一元多项式的乘积与和、顺序表求交集、出圈(约瑟夫环)

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

输入格式:

输入分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

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义一元多项式的结构体
struct Term {
    int coefficient; // 系数
    int exponent;    // 指数
};
// 求两个一元多项式的乘积
vector<Term> multiplyPolynomials(const vector<Term>& poly1, const vector<Term>& poly2) {
    vector<Term> result;
    for (const auto& term1 : poly1) {
        for (const auto& term2 : poly2) {
            Term product;
            product.coefficient = term1.coefficient * term2.coefficient;
            product.exponent = term1.exponent + term2.exponent;
            result.push_back(product);
        }
    }
    // 按指数递减排序
    sort(result.begin(), result.end(), [](const Term& t1, const Term& t2) {
        return t1.exponent > t2.exponent;
    });
    return result;
}
// 求两个一元多项式的和
vector<Term> addPolynomials(const vector<Term>& poly1, const vector<Term>& poly2) {
    vector<Term> result;
    size_t i = 0, j = 0;
    while (i < poly1.size() && j < poly2.size()) {
        if (poly1[i].exponent > poly2[j].exponent) {
            result.push_back(poly1[i]);
            i++;
        } else if (poly1[i].exponent < poly2[j].exponent) {
            result.push_back(poly2[j]);
            j++;
        } else {
            Term sum;
            sum.coefficient = poly1[i].coefficient + poly2[j].coefficient;
            sum.exponent = poly1[i].exponent;
            if (sum.coefficient != 0)
                result.push_back(sum);
            i++;
            j++;
        }
    }
    // 将未处理完的项加入结果中
    while (i < poly1.size()) {
        result.push_back(poly1[i]);
        i++;
    }
    while (j < poly2.size()) {
        result.push_back(poly2[j]);
        j++;
    }
    return result;
}
// 将结果中相同指数的项合并
vector<Term> mergeTerms(const vector<Term>& result) {
    vector<Term> merged = result; // 创建一个可修改的副本
    for (size_t i = 0; i < merged.size(); ++i) {
        int sum_coefficient = merged[i].coefficient;
        int exponent = merged[i].exponent;
        for (size_t j = i + 1; j < merged.size(); ++j) {
            if (merged[j].exponent == exponent) {
                sum_coefficient += merged[j].coefficient;
                // 避免重复累加
                merged[j].coefficient = 0;
            }
        }
        if (sum_coefficient != 0) {
            merged[i].coefficient = sum_coefficient;
        }
    }
    // 删除系数为0的项
    merged.erase(remove_if(merged.begin(), merged.end(), [](const Term& t) {
        return t.coefficient == 0;
    }), merged.end());
    return merged;
}
int main() {
    // 输入第一个多项式的非零项个数
    int n1;
    cin >> n1;
    vector<Term> poly1(n1);
    // 输入第一个多项式的系数和指数
    for (int i = 0; i < n1; i++) {
        cin >> poly1[i].coefficient >> poly1[i].exponent;
    }
    // 输入第二个多项式的非零项个数
    int n2;
    cin >> n2;
    vector<Term> poly2(n2);
    // 输入第二个多项式的系数和指数
    for (int i = 0; i < n2; i++) {
        cin >> poly2[i].coefficient >> poly2[i].exponent;
    }
    // 计算两个多项式的乘积
    vector<Term> product = multiplyPolynomials(poly1, poly2);
    // 合并同类项
    product = mergeTerms(product);
    // 输出乘积多项式的非零项系数和指数
    if (!product.empty()) {
        cout << product[0].coefficient << " " << product[0].exponent;
        for (size_t i = 1; i < product.size(); i++) {
            cout << " " << product[i].coefficient << " " << product[i].exponent;
        }
    } else {
        cout << "0 0";
    }
    cout << endl;
    // 计算两个多项式的和
    vector<Term> sum = addPolynomials(poly1, poly2);
    // 合并同类项
    sum = mergeTerms(sum);
    // 输出和多项式的非零项系数和指数
    if (!sum.empty()) {
        cout << sum[0].coefficient << " " << sum[0].exponent;
        for (size_t i = 1; i < sum.size(); i++) {
            cout << " " << sum[i].coefficient << " " << sum[i].exponent;
        }
    } else {
        cout << "0 0";
    }
    cout << endl;
    return 0;
}

其中,同类项合并时有抵消测试点没通过,可以试一下添一个bool类型变量来标记测试函数中是否有同类项合并的情况,需要改动以下代码:

// 将结果中相同指数的项合并
vector<Term> mergeTerms(const vector<Term>& result) {
    vector<Term> merged;
    for (size_t i = 0; i < result.size(); ++i) {
        int sum_coefficient = result[i].coefficient;
        int exponent = result[i].exponent;
        bool is_cancelled = false; // 标记项是否被抵消
        for (size_t j = i + 1; j < result.size(); ++j) {
            if (result[j].exponent == exponent) {
                sum_coefficient += result[j].coefficient;
                // 标记项已经被抵消
                if (result[j].coefficient != 0) {
                    is_cancelled = true;
                }
            }
        }
        // 如果项未被抵消且系数不为0,则添加到结果中
        if (!is_cancelled && sum_coefficient != 0) {
            merged.push_back({sum_coefficient, exponent});
        }
    }
    return merged;
}

2.顺序表求交集

用线性表的顺序表示方式表示集合,集合中的元素不重复,现有A、B两个集合,求C集合,C集合为AB两个集合的交集,C中元素的顺序按A中元素原有的顺序存放。函数void Intersection(Sqlist A,Sqlist B,Sqlist &C)即实现上述功能,请完善。
其中,
可以需要复制之前写的顺序表中的代码,自行判断需要复制哪些函数。

输入格式:

输入一组数据,该组测试实例包括两行分别为A,B集合。每一行首先是n(1<=n<=30),之后是n个元素,它们之间用空格隔开。
第一组输入数据:
6 1 3 4 5 6 7
6 1 2 3 4 5 8

第二组输入数据:
6 1 2 3 4 5 6
0

第三组输入数据:
6 1 2 3 4 5 6
3 6 8 9

第四组输入数据:
6 1 2 3 4 5 6
6 1 2 3 4 5 6

第五组输入数据:
3 6 8 9
6 1 2 3 4 5 6

第六组输入数据:
3 1 2 3
2 5 6

输出格式:

输出结果有一行,为求出的A,B集合的交集C集合,元素之间用空格间隔,C中元素的顺序按A中元素原有的顺序存放 。

#include<iostream>
using namespace std;
#define MAXSIZE 100
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
typedef struct
{
    ElemType* elem;
    int length;
}SqList;
//初始化线性表
Status InitList(SqList& L)//空的顺序表
{
    L.elem = new ElemType[MAXSIZE];//没有数组 那就new一个,长度为多少?不知道,所以就用最大长度来表示
    L.length = 0;//顺序表刚开始长度是0,没开辟之前长度是一个随机数字
    return OK;//告诉函数我做完了 可以返回了
}
//插入函数
Status ListInsert(SqList& L, int i, ElemType e)//&L改变了实参的值
{
    int j;
    if (i<1 || i>L.length + 1) return ERROR;//判断插入的位置不能比原有的顺序表长度长
    if (L.length == MAXSIZE) return ERROR;//如果当前长度等于数组最大了,那是不是就插入不了了
    for (j = L.length - 1; j >= i - 1; j--)//用一个循环,比如要插入二个元素,那么就从第二个开始把第三个挪到第四个位置,为插入的那个元素提供个位置。
        L.elem[j + 1] = L.elem[j];
    L.elem[i - 1] = e;//把要插入的值赋给对应的位置
    L.length++;//插入之后,数组的长度就对应加了个1
    return OK;//告诉函数 我做完了,可以退出了。
}
//取值函数
//获取顺序表长度L中第i个位置的元素  并存储在参数e中
Status GetElem(SqList L, int i, ElemType& e)//e要使用c++的引用来改变实参的值,
{
    if (i<1 || i>L.length)return ERROR;//先判断要取的值在不在顺序表这个范围内
    e = L.elem[i - 1];//第i个元素值赋给e,因为数组第一个为a[0]  顺序表第一个元素为1,所以要用elem【i-1】来表示
    return OK;
}
// 打印整张表
void ListPrint(SqList L) {
    if (L.length == 0) {
        cout << "NULL\n";
        return;
    }
    for (int i = 0; i < L.length; i++) {
        cout << L.elem[i] << " ";
    }
    cout << endl;
}
//交集
void Intersection(SqList A, SqList B, SqList& C) {//传入ab俩集合 然后c集合要改变 所以用c++的引用&
    InitList(C); // 先把用于存数组的集合c初始化
    for (int i = 0; i < A.length; i++) {
        ElemType e;
        GetElem(A, i + 1, e);//获得A集合的元素取值,用取值函数,用顺序表A
        for (int j = 0; j < B.length; j++) {
            if (e == B.elem[j])//判断b和a有没有重复的元素
            {
                ListInsert(C, C.length + 1, e);//没有的话 就插入c中
                break;
            }
        }
    }
}
int main() {
    SqList A, B, C;
    int n, x;
    //初始化集合A、B、C
    InitList(A);
    InitList(B);
    InitList(C);
    //输入集合A的元素
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> x;
        ListInsert(A, i + 1, x);
    }
    //输入集合B的元素
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> x;
        ListInsert(B, i + 1, x);
    }
    // 求集合A和B的交集C
    Intersection(A, B, C);
    // 打印集合C
    ListPrint(C);
    return 0;
}

最主要的是集合的那个函数,用双层循环来判断A B中有没有相同的元素,没有的话直接插入C中,这样会避免有重复的值插入进去,也避免了漏插入进去的情况。

3.出圈(约瑟夫环)

设有N个人围坐一圈并按顺时针方向从1到N编号,从第n个人开始进行1到m的报数, 报数到第m个人, 此人出圈, 再从他的下一个人重新开始1到m的报数,如此进行下去直到所有的人都出圈为止。现要求按出圈次序,给出这N个人的顺序表。这是一个编程题模板。请在这里写题目描述。例如:本题目要求读入2个整数A和B,然后输出它们的和。

输入格式:

分别输入N(N<=100),n,m。

输出格式:

输出N个人的出圈顺序。

输入样例:

10 2 3

输出样例:

4 7 10 3 8 2 9 6 1 5 
#include <iostream>
using namespace std;
int quanrenshu(int N, int n, int m) {
    int sump[100]; // 数组大小可根据题目要求调整
    // 给每一个人都编上号 排上序号
    for (int i = 0; i < N; ++i) {
        sump[i] = i + 1;
    }
    int  out= n - 1;//第n-1个人计入要淘汰的位置
    while (N > 0) {
        out= (out+ m - 1) % N; // 计算出圈位置
        cout << sump[out] << " "; // 用总人数输出出圈的
        //移动数组元素
        for (int i = out; i < N - 1; i++) {
            sump[i] = sump[i + 1];
        }
        N--; //每走一个人 总人数就-1
    }
    return 0;
}
int main() {
    int N, n, m;
    cin >> N >> n >> m;
    quanrenshu(N, n, m);
    return 0;
}

 

使用一个函数quanrenshu()来从主函数传入,在这个函数中

int quanrenshu(int N, int n, int m) {
    int sump[100]; //大小为100的数组   存储参与的人员编号
    // 给每一个人都编上号 排上序号 存到sump中
    for (int i = 0; i < N; ++i) {
        sump[i] = i + 1;
    }
    int  out= n - 1;//设置初始淘汰的位置为n-1  从第n个人开始报数,不要从n+1个开始,否则到最后总人数会多一个或者少一个的情况
    while (N > 0) {
        out= (out+ m - 1) % N; // 每次要淘汰的位置
        cout << sump[out] << " "; // 输出淘汰人的编号
        for (int i = out; i < N - 1; i++) {//移动数组,把淘汰的人从数组移除  然后接着进入循环淘汰
            sump[i] = sump[i + 1];
        }
        N--; //每走一个人 总人数就-1
    }
    return 0;
}

 int sump是存储参与人员的编号

计算淘汰人员的编号为:(out+m-1)%N

必须从n-1开始淘汰  另一个意思就是从n开始报数

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值