【问题标题】:Printing the result linked list in correct order以正确的顺序打印结果链表
【发布时间】:2021-01-27 04:41:05
【问题描述】:

我正在编写一个程序,它使用链表将 2 个给定多项式添加到第三个多项式中,但结果链表顺序相反,我无法理解它

输入: (10x7 + 5x4 + 3x2 + 5) + (3x8 + 3x4 + 3x -6)

结果: -1x0 + 3x + 3x2 + 8x4 + 10x7 + 3x8

我想要它: 3x8 + 10x7 + 8x4 + 3x2 +3x -1x0

这些是函数:

typedef struct term
{
    int coef;
    int exp;
    struct term *next;
} term;
        
void Push2(term **headRef, int coef, int exp)
{
    struct term *newNode = (term *)malloc(sizeof(term));
    if (coef == 0)
        return;
            
    newNode->coef = coef;
    newNode->exp = exp;
    newNode->next = *headRef;
    *headRef = newNode;
}

term *addPolynomials2(term *h1, term *h2)
{
    term *current1 = h1;
    term *current2 = h2;
        
    term *new = NULL;
    while (current1 && current2)
    {
        if (current1->exp == current2->exp)
        {
            Push2(&new, (current1->coef + current2->coef), current1->exp);
            current1 = current1->next;
            current2 = current2->next;
        }
        else if (current1->exp > current2->exp)
        
        {
            Push2(&new, current1->coef, current1->exp);
            current1 = current1->next;
        }
        
        else
        {
            Push2(&new, current2->coef, current2->exp);
            current2 = current2->next;
        }
    }

    while (current1)
    {
        Push2(&new, current1->coef, current1->exp);
        current1 = current1->next;
    }

    while (current2)
    {
        Push2(&new, current2->coef, current2->exp);
        current2 = current2->next;
    }

    return new;
}

void printTerm(term head)
{
    printf("%dx%d ", head.coef, head.exp);
}

void printPolynomial(term *head)
{
    if (head == 0)
        return;
            
    printTerm(*head);
    printPolynomial(head->next);
}

void addPolynomialsTest2()
{
    term *head1 = NULL;
    term *head2 = NULL;
    term *new;
    int a[] = {10, 0, 0, 5, 0, 3, 0, 5};
    
    int b[] = {7, 6, 5, 4, 3, 2, 1, 0};
    for (int i = sizeof(a) / sizeof(int) - 1; i >= 0; i--)
    {
        Push2(&head1, a[i], b[i]);
    }
    
    int c[] = {8, 7, 6, 5, 4, 3, 2, 1, 0};
    int d[] = {3, 0, 0, 0, 3, 0, 0, 3, -6};
    for (int i = sizeof(d) / sizeof(int) - 1; i >= 0; i--)
    {
    
        Push2(&head2, d[i], c[i]);
    }
    printf("F(x)= ");
    printPolynomial(head2);
    printf("\n");
    printf("Q(x)= ");
    printPolynomial(head1);
    printf("\n");
    printf("F(x) + Q(X)= ");
    new = addPolynomials2(head1, head2);
    printPolynomial(new);
    printf("\n");
    printf("\n");
}

【问题讨论】:

  • Push2 将新元素放在前面。因此,当您推送所有术语时,您推送的最后一个将位于列表的最前面,并且会以相反的顺序排列。如果您希望它们保持有序,请更改 Push2() 以在末尾添加新元素。
  • 或者逆序打印列表。使用递归很容易做到这一点。
  • 我尝试反向打印它仍然没有给出正确的输出
  • @Barmar 3x4 != 8x4
  • 你为什么要3x4?您在第一个输入中有5x4,在第二个输入中有3x4。当你添加它们时,你会得到8x4

标签: c linked-list


【解决方案1】:

您的Push2 总是推到列表的前面(即头部)。

组合/添加时,需要一个追加到列表tail的推送。

另外,我认为你希望总和有 8x4 3x4 如你所说(即你的程序是正确的,除了顺序相反) 因为每个输入多项式都有一个x4 项。

此外,您的打印多项式函数不需要是递归的。

并且,不要转换malloc的结果


这是一个带有一些调试打印的重构版本。我为追加创建了第二个推送功能。忽略TERM [宏]——在我发现真正的问题之前,这是一次不完整的清晰尝试。

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

typedef struct term {
    int coef;
    int exp;
    struct term *next;
} term;

#ifdef DEBUG
#define dbgprt(_fmt...) \
    printf(_fmt)
#else
#define dbgprt(_fmt...) \
    do { } while (0)
#endif

typedef void (*pushfnc_p)(term **headRef, int coef, int exp);

void
Push2(term **headRef, int coef, int exp)
{
    term *newNode = malloc(sizeof(*newNode));

    if (coef == 0)
        return;

    newNode->coef = coef;
    newNode->exp = exp;
    newNode->next = *headRef;
    *headRef = newNode;
}

void
Push2_tail(term **headRef, int coef, int exp)
{
    term *newNode = malloc(sizeof(*newNode));
    term *head = *headRef;

    if (coef == 0)
        return;

    term *prev = NULL;
    for (struct term *cur = head;  cur != NULL;  cur = cur->next)
        prev = cur;

    newNode->coef = coef;
    newNode->exp = exp;
    newNode->next = NULL;

    if (prev != NULL)
        prev->next = newNode;
    else
        head = newNode;

    *headRef = head;
}

term *
addPolynomials2(term *h1, term *h2)
{
    term *current1 = h1;
    term *current2 = h2;
#if 0
    pushfnc_p push = Push2;
#else
    pushfnc_p push = Push2_tail;
#endif

    term *new = NULL;

    while (current1 && current2) {
        dbgprt("add: DUAL current1=%dX%d current2=%dX%d\n",
            current1->coef,current1->exp,
            current2->coef,current2->exp);

        if (current1->exp == current2->exp) {
            dbgprt("add: SAME\n");
            push(&new, (current1->coef + current2->coef), current1->exp);
            current1 = current1->next;
            current2 = current2->next;
            continue;
        }

        if (current1->exp > current2->exp) {
            dbgprt("add: CURR1\n");
            push(&new, current1->coef, current1->exp);
            current1 = current1->next;
            continue;
        }

        dbgprt("add: CURR2\n");
        push(&new, current2->coef, current2->exp);
        current2 = current2->next;
    }

    while (current1) {
        dbgprt("add: POST1 current1=%dX%d\n",
            current1->coef,current1->exp);
        push(&new, current1->coef, current1->exp);
        current1 = current1->next;
    }

    while (current2) {
        dbgprt("add: POST2 current2=%dX%d\n",
            current2->coef,current2->exp);
        push(&new, current2->coef, current2->exp);
        current2 = current2->next;
    }

    return new;
}

void
printTerm(term *head)
{
    printf("%dx%d ", head->coef, head->exp);
}

void
printPolynomial(term *head)
{

    for (;  head != NULL;  head = head->next)
        printTerm(head);
}

#define TERM(_coef,_exp) \
    { .coef = _coef, .exp = _exp },

void
addPolynomialsTest2(void)
{
    term *head1 = NULL;
    term *head2 = NULL;
    term *new;

#if 1
    int a[] = { 10, 0, 0, 5, 0, 3, 0, 5 };
    int b[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
    for (int i = sizeof(a) / sizeof(int) - 1; i >= 0; i--) {
        Push2(&head1, a[i], b[i]);
    }

    int c[] = { 8, 7, 6, 5, 4, 3, 2, 1, 0 };
    int d[] = { 3, 0, 0, 0, 3, 0, 0, 3, -6 };
    for (int i = sizeof(d) / sizeof(int) - 1; i >= 0; i--) {
        Push2(&head2, d[i], c[i]);
    }
#else
    term a[] = {
        TERM(10,7)
        TERM(0,6)
        TERM(0,5)
        TERM(5,4)
        TERM(0,3)
        TERM(3,2)
        TERM(0,5)
    };
    for (int i = sizeof(a) / sizeof(term) - 1; i >= 0; i--) {
        term *t = &a[i];
        Push2(&head1,t->coef,t->exp);
    }
#endif

    printf("F(x)= ");
    printPolynomial(head2);
    printf("\n");
    printf("Q(x)= ");
    printPolynomial(head1);
    printf("\n");
    printf("F(x) + Q(X)= ");
    new = addPolynomials2(head1, head2);
    printPolynomial(new);
    printf("\n");
    printf("\n");
}

int
main(void)
{
    addPolynomialsTest2();
    return 0;
}

这是程序输出:

F(x)= 3x8 3x4 3x1 -6x0
Q(x)= 10x7 5x4 3x2 5x0
F(x) + Q(X)= 3x8 10x7 8x4 3x2 3x1 -1x0

更新:

我尝试通过反向打印结果而不在末尾插入,但输出更奇怪知道为什么吗?

不完全确定。听起来像是两个错误使一个正确......见下文。

创建多项式时,您的代码使用前推确实可以工作,但是,IMO,它有点复杂,因为您必须遍历数组以相反的顺序。

然而,添加函数确实需要push-to-tail。使用 push-to-front,添加将失败。因此,尝试以相反的顺序打印以“补偿”不正确的添加函数可能不是有效的修复方法。

因此,在原始代码中,您有两个输入多项式按从高到低的顺序 [如我们所愿],但 输出 多项式的顺序 颠倒了。

因此,如果您尝试将输出添加到其他内容(例如再次输入其中一个),它将中断

因此,通过反向打印进行补偿不能解决问题。它仅用于打印。

实际上并不需要推到前面。我得到了TERM 宏工作。它使用push-to-tail并从0到N遍历数组[更容易理解]。

所以,这是,IMO,更干净一点:

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

typedef struct term {
    int coef;
    int exp;
    struct term *next;
} term;

#ifdef DEBUG
#define dbgprt(_fmt...) \
    printf(_fmt)
#else
#define dbgprt(_fmt...) \
    do { } while (0)
#endif

typedef void (*pushfnc_p)(term **headRef, int coef, int exp);

void
Push2(term **headRef, int coef, int exp)
{
    term *newNode = malloc(sizeof(*newNode));

    if (coef == 0)
        return;

    newNode->coef = coef;
    newNode->exp = exp;
    newNode->next = *headRef;
    *headRef = newNode;
}

void
Push2_tail(term **headRef, int coef, int exp)
{
    term *newNode = malloc(sizeof(*newNode));
    term *head = *headRef;

    if (coef == 0)
        return;

    term *prev = NULL;
    for (struct term *cur = head;  cur != NULL;  cur = cur->next)
        prev = cur;

    newNode->coef = coef;
    newNode->exp = exp;
    newNode->next = NULL;

    if (prev != NULL)
        prev->next = newNode;
    else
        head = newNode;

    *headRef = head;
}

term *
addPolynomials2(term *h1, term *h2)
{
    term *current1 = h1;
    term *current2 = h2;
#if 0
    pushfnc_p push = Push2;
#else
    pushfnc_p push = Push2_tail;
#endif

    term *new = NULL;

    while (current1 && current2) {
        dbgprt("add: DUAL current1=%dX%d current2=%dX%d\n",
            current1->coef,current1->exp,
            current2->coef,current2->exp);

        if (current1->exp == current2->exp) {
            dbgprt("add: SAME\n");
            push(&new, (current1->coef + current2->coef), current1->exp);
            current1 = current1->next;
            current2 = current2->next;
            continue;
        }

        if (current1->exp > current2->exp) {
            dbgprt("add: CURR1\n");
            push(&new, current1->coef, current1->exp);
            current1 = current1->next;
            continue;
        }

        dbgprt("add: CURR2\n");
        push(&new, current2->coef, current2->exp);
        current2 = current2->next;
    }

    while (current1) {
        dbgprt("add: POST1 current1=%dX%d\n",
            current1->coef,current1->exp);
        push(&new, current1->coef, current1->exp);
        current1 = current1->next;
    }

    while (current2) {
        dbgprt("add: POST2 current2=%dX%d\n",
            current2->coef,current2->exp);
        push(&new, current2->coef, current2->exp);
        current2 = current2->next;
    }

    return new;
}

void
printTerm(term *head)
{
    printf("%dx%d ", head->coef, head->exp);
}

void
printPolynomial(term *head)
{

    for (;  head != NULL;  head = head->next)
        printTerm(head);
}

#define TERM(_coef,_exp) \
    { .coef = _coef, .exp = _exp },

void
addPolynomialsTest2(void)
{
    term *head1 = NULL;
    term *head2 = NULL;
    term *new;

#if 0
    int a[] = { 10, 0, 0, 5, 0, 3, 0, 5 };
    int b[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
    for (int i = sizeof(a) / sizeof(int) - 1; i >= 0; i--) {
        Push2(&head1, a[i], b[i]);
    }

    int c[] = { 8, 7, 6, 5, 4, 3, 2, 1, 0 };
    int d[] = { 3, 0, 0, 0, 3, 0, 0, 3, -6 };
    for (int i = sizeof(d) / sizeof(int) - 1; i >= 0; i--) {
        Push2(&head2, d[i], c[i]);
    }
#else
    term ab[] = {
        TERM(10,7)
        TERM(0,6)
        TERM(0,5)
        TERM(5,4)
        TERM(0,3)
        TERM(3,2)
        TERM(0,5)
    };
    for (int i = 0;  i < sizeof(ab) / sizeof(term); ++i) {
        term *t = &ab[i];
        Push2_tail(&head1,t->coef,t->exp);
    }

    term cd[] = {
        TERM(3,8)
        TERM(0,7)
        TERM(0,6)
        TERM(0,5)
        TERM(3,4)
        TERM(0,3)
        TERM(0,2)
        TERM(3,1)
        TERM(-6,0)
    };
    for (int i = 0;  i < sizeof(cd) / sizeof(term); ++i) {
        term *t = &cd[i];
        Push2_tail(&head2,t->coef,t->exp);
    }
#endif

    printf("F(x)= ");
    printPolynomial(head2);
    printf("\n");
    printf("Q(x)= ");
    printPolynomial(head1);
    printf("\n");
    printf("F(x) + Q(X)= ");
    new = addPolynomials2(head1, head2);
    printPolynomial(new);
    printf("\n");
    printf("\n");
}

int
main(void)
{
    addPolynomialsTest2();
    return 0;
}

这是一个有争议的问题,因为以相反的顺序构造输出是不正确的(即这样做)。

但是,现在,我明白您为什么想要一个 递归 函数来打印多项式了。

要以 reverse 顺序打印,我认为该函数必须递归地打印 currentafter呼唤自己。我还没有想到[或测试过]:

void
printTerm(term *head)
{
    printf("%dx%d ", head->coef, head->exp);
}

void
printPolynomial(term *head)
{

    if (head == 0)
        return;

#if 0
    printTerm(head);
    printPolynomial(head->next);
#else
    printPolynomial(head->next);
    printTerm(head);
#endif
}

可能修复结果多项式的打印。

但是,这样做会破坏两个输入多项式的打印。

【讨论】:

  • 谢谢我尝试通过反向打印结果而不在末尾插入但输出更奇怪知道为什么吗?
【解决方案2】:
void Reverse(term *Node)
{
if(Node== NULL) return;

Reverse(Node->next);
printTerm(*Node);
}

并调用 Reverse(New) 而不是 PrintPolynomial(New)

输出:F(x) + Q(X)= 3x8 10x7 8x4 3x2 3x1 -1x0

完整解决方案:

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

typedef struct term
{
int coef;
int exp;
struct term *next;

} term;


void Push2(term **headRef, int coef, int exp)
{
struct term *NewNode = (term *)malloc(sizeof(term));
if (coef == 0)
    return;

NewNode->coef = coef;
NewNode->exp = exp;
NewNode->next = *headRef;
*headRef = NewNode;
}

term *addPolynomials2(term *h1, term *h2)
{
term *current1 = h1;
term *current2 = h2;

term *New = NULL;
while (current1 && current2)

{
    if (current1->exp == current2->exp)
    {
        Push2(&New, (current1->coef + current2->coef), current1->exp);
        current1 = current1->next;
        current2 = current2->next;
    }
    else if (current1->exp > current2->exp)

    {
        Push2(&New, current1->coef, current1->exp);
        current1 = current1->next;
    }

    else
    {
        Push2(&New, current2->coef, current2->exp);
        current2 = current2->next;
    }
}
while (current1)
{
    Push2(&New, current1->coef, current1->exp);
    current1 = current1->next;
}
while (current2)
{
    Push2(&New, current2->coef, current2->exp);
    current2 = current2->next;
}
return New;
}

void printTerm(term head)
{
 printf("%dx%d ", head.coef, head.exp);
}

void Reverse(term *Node)
{
if(Node== NULL)
    return;
Reverse(Node->next);
printTerm(*Node);
}

void printPolynomial(term *head)
{
if (head == 0)
    return;

printTerm(*head);
printPolynomial(head->next);
 }
void addPolynomialsTest2()
{
term *head1 = NULL;
term *head2 = NULL;
term *New;
int a[] = {10, 0, 0, 5, 0, 3, 0, 5};

int b[] = {7, 6, 5, 4, 3, 2, 1, 0};
for (int i = sizeof(a) / sizeof(int) - 1; i >= 0; i--)
{

    Push2(&head1, a[i], b[i]);
}

int c[] = {8, 7, 6, 5, 4, 3, 2, 1, 0};
int d[] = {3, 0, 0, 0, 3, 0, 0, 3, -6};
for (int i = sizeof(d) / sizeof(int) - 1; i >= 0; i--)
{

    Push2(&head2, d[i], c[i]);
}
printf("F(x)= ");
printPolynomial(head2);
printf("\n");
printf("Q(x)= ");
printPolynomial(head1);
printf("\n");
printf("F(x) + Q(X)= ");
New = addPolynomials2(head1, head2);

while(New!= NULL)
{
    printTerm(*New);
    New = New->next;
}
Reverse(New);
printf("\n");
printf("\n");
}
int main()
{
addPolynomialsTest2();
}

【讨论】:

  • 我接近了这个解决方案,但没有成功
  • 添加完整代码,请查看@mrreaper72
猜你喜欢
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多