数据结构与算法-线性表-案例分析与实现

线性表

1.6 案例分析与实现

1.6.1 多项式运算

使用数组 p 表示:数组中每个分量 p[i] 表示多项式每项的系数 p,数组分量的下标 i 即对应每项的指数。如下图:

在这里插入图片描述
然后把两个数组对应的分量项相加即可。实现代码参考如下:

// 计算两个多项式相关系数的和,返回结果的系数数组
// pa和pb分别为两个多项式的系数数组
// size_a和size_b分别为两个多项式的系数数组长度
// 返回值为结果多项式的系数数组
int *add_polynomials(int *pa, int *pb, int size_a, int size_b)
{
    // 结果多项式的系数数组长度
    size_t size_c = size_a > size_b ? size_a : size_b;
    // 分配内存空间给结果多项式的系数数组
    int *pc = (int *)malloc(size_c * sizeof(int));
    if (pc == NULL)
    {
        printf("Memory allocation failed\n");
        return NULL;
    }

    // 初始化结果多项式的系数为0
    for (int i = 0; i < size_c; i++)
    {
        pc[i] = 0;
    }

    // 将pa和pb的系数相加到pc中
    for (int i = 0; i < size_a; i++)
    {
        pc[i] += pa[i];
    }
    for (int i = 0; i < size_b; i++)
    {
        pc[i] += pb[i];
    }
    return pc;
}

一个示例:

// 定义多项式pa的系数分别为10, 5, -4, 3, 2
int pa[] = {10, 5, -4, 3, 2};
// 定义多项式pb的系数分别为-3, 8, 4, 0, -5, 7, 2
int pb[] = {-3, 8, 4, 0, -5, 7, 2};

size_t size_a = sizeof(pa) / sizeof(pa[0]);       // 计算多项式pa的系数数组长度
size_t size_b = sizeof(pb) / sizeof(pb[0]);       // 计算多项式pb的系数数组长度
printf("size_a=%d, size_b=%d\n", size_a, size_b); // 打印多项式的系数数组长度

int *pc = add_polynomials(pa, pb, size_a, size_b);
if (pc == NULL)
{
	printf("Failed to add polynomials\n");
	return 1; // 如果内存分配失败,返回错误
}

size_t size_c = size_a > size_b ? size_a : size_b; // size_c为结果多项式的系数数组长度
printf("size_c=%d\n", size_c);                     // 打印结果多项式的系数数组长度
// 打印结果多项式的系数
for (int i = 0; i < size_c; i++)
	printf("%d ", pc[i]);

运行程序,打印的内容如下:

size_a=5, size_b=7
size_c=7
7 13 0 3 -3 7 2 

时间复杂度取决于较长的多项式,为 O(n)

1.6.2 稀疏多项式运算

如果要给多项式是稀疏多项式,那么用顺序表实现比较浪费空间,此时可以考虑使用链表实现。

【算法步骤】

思路和数据结构如下图:

在这里插入图片描述

【代码实现】

核心算法实现起来并不难理解,但是在前期要初始化两个相加的多项式,还是比较麻烦些。

1)初始化多项式结点的结构,这个参考视频教程即可。

// 定义多项式节点结构体
// PNode结构体表示多项式的一个节点
// 包含系数、指数和指向下一个节点的指针
typedef struct PNode
{
	int coef;           // 系数
	int expn;           // 指数
	struct PNode *next; // 指向下一个节点的指针
} PNode, *Polynomial;

2)要按照书上的多项式进行初始化,需要用户输入多项式的数据,有点麻烦,于是考虑封装一个方法进行批量处理。

// 尾插法创建多项式链表
Status createPolynomialTail(Polynomial *polynomia, PNode nodes[], int n)
{
	*polynomia = (Polynomial)malloc(sizeof(PNode)); // 创建头结点
	if (*polynomia == NULL)
	{
		return OVERFLOW;
	}
	(*polynomia)->next = NULL; // 初始化头结点的next指针为NULL

	// 创建尾结点,一开始尾结点指向头节点。
	PNode *tailNode;
	tailNode = *polynomia;

	PNode *newNode; // 新结点指针
	for (int i = 1; i <= n; i++)
	{
		newNode = (PNode *)malloc(sizeof(PNode)); // 创建新结点
		if (newNode == NULL)
		{
			return OVERFLOW;
		}
		newNode->coef = nodes[i - 1].coef; // 设置新结点的数据
		newNode->expn = nodes[i - 1].expn; // 设置新结点的指数
		newNode->next = NULL;              // 将新结点的next指针设置为NULL

		tailNode->next = newNode; // 将当前尾结点的next指针指向新结点
		tailNode = newNode;       // 更新尾结点为新结点
	}
	return OK;
}

在使用方面就比较容易了,初始化多项式就可以通过如下方式进行:

/* 1. 创建多项式链表1 */
Polynomial p1;
PNode nodes1[] = {
	{7, 0, NULL},  // 第一个节点,系数为7,指数为0
	{3, 1, NULL},  // 第二个节点,系数为3,指数为1
	{9, 8, NULL},  // 第三个节点,系数为9,指数为8
	{5, 17, NULL}, // 第四个节点,系数为5,指数为17
};
createPolynomialTail(&p1, nodes1, sizeof(nodes1) / sizeof(nodes1[0]));
PrintList(&p1);

3)实现两个多项式相加。

// 两个多项式的各个系数相加
int addPolynomials(Polynomial *p1, Polynomial *p2, Polynomial *p3)
{
    // 初始化结果多项式链表
    *p3 = (Polynomial)malloc(sizeof(PNode));
    (*p3)->next = NULL;    // 初始化结果链表的头结点
    PNode *tailNode = *p3; // 尾结点指针,初始指向结果链表的头结点

    PNode *current1 = (*p1)->next; // p1的当前结点
    PNode *current2 = (*p2)->next; // p2的当前结点
    while (current1 != NULL && current2 != NULL)
    {
        PNode *newNode = (PNode *)malloc(sizeof(PNode)); // 创建新结点

        if (current1->expn < current2->expn) // p1的指数小于p2的指数
        {
            newNode->coef = current1->coef; // 直接复制p1的系数
            newNode->expn = current1->expn; // 直接复制p1的指数
            current1 = current1->next;      // 移动到p1的下一个结点
        }
        else if (current1->expn > current2->expn) // p1的指数大于p2的指数
        {
            newNode->coef = current2->coef; // 直接复制p2的系数
            newNode->expn = current2->expn; // 直接复制p2的指数
            current2 = current2->next;      // 移动到p2的下一个结点
        }
        else // p1和p2的指数相等
        {
            newNode->coef = current1->coef + current2->coef; // 系数相加
            newNode->expn = current1->expn;                  // 指数相同,直接复制
            current1 = current1->next;                       // 移动到p1的下一个结点
            current2 = current2->next;                       // 移动到p2的下一个结点
        }

        newNode->next = NULL;     // 新结点的next指针设置为NULL
        tailNode->next = newNode; // 将当前尾结点指向新结点
        tailNode = newNode;       // 更新尾结点为新结点
    }

    // 处理剩余的p1或p2结点
    while (current1 != NULL) // 如果p1还有剩余结点
    {
        PNode *newNode = (PNode *)malloc(sizeof(PNode)); // 创建新结点
        newNode->coef = current1->coef;                  // 复制p1的系数
        newNode->expn = current1->expn;                  // 复制p1的指数
        newNode->next = NULL;                            // 新结点的next指针设置为NULL

        tailNode->next = newNode;  // 将当前尾结点指向新结点
        tailNode = newNode;        // 更新尾结点为新结点
        current1 = current1->next; // 移动到p1的下一个结点
    }
    while (current2 != NULL) // 如果p2还有剩余结点
    {
        PNode *newNode = (PNode *)malloc(sizeof(PNode)); // 创建新结点
        newNode->coef = current2->coef;                  // 复制p2的系数
        newNode->expn = current2->expn;                  // 复制p2的指数
        newNode->next = NULL;                            // 新结点的next指针设置为NULL

        tailNode->next = newNode;  // 将当前尾结点指向新结点
        tailNode = newNode;        // 更新尾结点为新结点
        current2 = current2->next; // 移动到p2的下一个结点
    }

    return OK; // 返回成功状态
}

和书上不同,这里构造了一个新的链表进行存储结果,不在原有的基础上处理。因为在有一些场景下,可能原有的多项式还需要使用。

【算法分析】

假设两个多项式的项数分别为 m 和 n,该算法的时间复杂度为 O(m + n),空间复杂度方面书中的方法是为O(1),这里我写的方法需要一个新的链表,空间复杂度最差为 O(m+n)。

1.6.3 图书信息管理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴空闲雲

感谢家人们的投喂

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值