数据结构实验2

1、分别创建两个有序的单链表(每个表的元素个数以及每个元素的值在运行时由键盘输入),现将两个单链表合并,并保证新表依然为有序的单链表。

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

// 定义单链表结构体
typedef struct ListNode {
    int data;
    struct ListNode *next;
} ListNode;

//创建一个单链表,返回头节点的指针
ListNode* createList() {
    ListNode *head = NULL, *p = NULL, *q = NULL;
    int n = 0, data = 0;
    printf("请输入要创建单链表的长度:");
    scanf("%d", &n);

    // 依次读入每个元素,创建新的节点,并插入链表尾部
    for (int i = 1; i <= n; ++i) {
        printf("请输入第%d个节点值:", i);
        scanf("%d", &data);

        // 创建新节点
        p = (ListNode*) malloc(sizeof(ListNode));
        p->data = data;
        p->next = NULL;

        // 插入链表尾部
        if (head == NULL) {
            head = p;
        } else {
            q = head;
            while (q->next != NULL) {
                q = q->next;
            }
            q->next = p;
        }
    }
    return head;
}

//合并两个有序的单链表,返回合并后的链表头节点的指针
ListNode* mergeLists(ListNode* list1, ListNode* list2) {
    if (list1 == NULL) {
        return list2;
    }
    if (list2 == NULL) {
        return list1;
    }

    // 创建哨兵节点,简化代码逻辑
    ListNode sentinel = {0, NULL};
    ListNode *tail = &sentinel;

    // 依次比较两个链表的节点,并将较小的节点插入新的链表尾部
    while (list1 != NULL && list2 != NULL) {
        if (list1->data <= list2->data) {
            tail->next = list1;
            list1 = list1->next;
        } else {
            tail->next = list2;
            list2 = list2->next;
        }
        tail = tail->next;
    }

    // 将剩余节点插入新链表尾部
    if (list1 != NULL) {
        tail->next = list1;
    }
    if (list2 != NULL) {
        tail->next = list2;
    }

    // 返回哨兵节点的下一个节点作为新链表头节点
    return sentinel.next;
}

//遍历单链表,并打印每个节点的值
void traverseList(ListNode* head) {
    printf("合并后单链表:");
    while (head != NULL) {
        printf("%d ", head->data);
        head = head->next;
    }
    printf("\n");
}

int main() {
    ListNode *list1 = createList();
    ListNode *list2 = createList();
    ListNode *mergedList = mergeLists(list1, list2);
    traverseList(mergedList);

    return 0;
}

各个函数的实现流程:

1. createList

用于创建一个单链表,返回头节点的指针。先读入要创建的链表长度,然后依次读入每个节点的值,创建新节点,并将其插入到链表尾部。需要注意的是,在第一次插入节点时,需要将头节点指针指向该节点。

2. mergeLists

用于合并两个有序的单链表,返回合并后的链表头节点的指针。如果其中一个链表为空,则直接返回另一个链表头节点的指针。为了简化代码逻辑,该函数先创建一个哨兵节点,指向新链表的头节点。然后依次比较两个链表的节点值,将较小的节点插入到新链表尾部。最后将剩余节点直接接到新链表尾部。

3. traverseList

用于遍历单链表,并打印每个节点的值。只需从头节点开始依次遍历每个节点,输出其数据域的值即可。

 

2、创建以单链表存放的两个多项式(为便于测试,每项的系数和指数可放在结点的结构体中),求二者之和,结果存放在第三个链表中。

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

// 定义单链表结构体
typedef struct ListNode {
    int coef;
    int expn;
    struct ListNode *next;
} ListNode;

//创建一个单链表,返回头节点的指针
ListNode* createList() {
    ListNode *head = NULL, *p = NULL, *q = NULL;
    int n = 0, coef = 0, expn = 0;
    printf("请输入单链表的长度:");
    scanf("%d", &n);

    // 依次读入每个元素,创建新的节点,并插入链表尾部
    for (int i = 1; i <= n; ++i) {
        printf("请输入第%d个节点的系数和指数,中间以空格分隔:", i);
        scanf("%d %d", &coef, &expn);

        // 创建新节点
        p = (ListNode*) malloc(sizeof(ListNode));
        p->coef = coef;
        p->expn = expn;
        p->next = NULL;

        // 插入链表尾部
        if (head == NULL) {
            head = p;
        } else {
            q = head;
            while (q->next != NULL) {
                q = q->next;
            }
            q->next = p;
        }
    }
    return head;
}

//遍历单链表,并打印每个节点的值
void traverseList(ListNode* head) {
    printf("遍历单链表:");
    while (head != NULL) {
        printf("%dx^%d+ ", head->coef, head->expn);
        head = head->next;
    }
    printf("\n");
}

//实现两个多项式的加法,返回新链表头节点的指针
ListNode* addPolynomials(ListNode* poly1, ListNode* poly2) {
    ListNode sentinel = {0, 0, NULL};
    ListNode *tail = &sentinel;

    while (poly1 != NULL && poly2 != NULL) {
        if (poly1->expn < poly2->expn) {
            // 创建新节点,并插入尾部
            ListNode *p = (ListNode*) malloc(sizeof(ListNode));
            p->coef = poly1->coef;
            p->expn = poly1->expn;
            p->next = NULL;
            tail->next = p;
            tail = tail->next;
            poly1 = poly1->next;
        } else if (poly1->expn > poly2->expn) {
            // 创建新节点,并插入尾部
            ListNode *p = (ListNode*) malloc(sizeof(ListNode));
            p->coef = poly2->coef;
            p->expn = poly2->expn;
            p->next = NULL;
            tail->next = p;
            tail = tail->next;
            poly2 = poly2->next;
        } else {
            int sum = poly1->coef + poly2->coef;
            if (sum != 0) {
                // 创建新节点,并插入尾部
                ListNode *p = (ListNode*) malloc(sizeof(ListNode));
                p->coef = sum;
                p->expn = poly1->expn;
                p->next = NULL;
                tail->next = p;
                tail = tail->next;
            }
            poly1 = poly1->next;
            poly2 = poly2->next;
        }
    }

    // 插入未处理完的节点
    if (poly1 != NULL) {
        tail->next = poly1;
    }
    if (poly2 != NULL) {
        tail->next = poly2;
    }

    // 删除哨兵节点,返回新链表头节点
    ListNode *result = sentinel.next;
    free(&sentinel);
    return result;
}

int main() {
    ListNode *poly1 = createList();
    ListNode *poly2 = createList();

    traverseList(poly1);
    traverseList(poly2);

    ListNode *result = addPolynomials(poly1, poly2);

    traverseList(result);

    return 0;
}

每个函数的实现流程:

1. `createList()`: 创建一个单链表,并返回头节点的指针。
   - 首先通过用户输入获取需要创建的单链表的长度。
   - 然后使用循环逐个读入每个节点的系数和指数。
   - 每次读入一个节点时,创建新的节点并赋值,然后插入到链表尾部。
   - 循环结束后返回头节点的指针。

2. `traverseList(ListNode* head)`: 遍历链表,并打印每个节点的系数和指数。
   - 通过循环遍历链表中的每个节点。
   - 对于每个节点,打印其系数和指数。
   - 循环结束后输出换行符。

3. `addPolynomials(ListNode* poly1, ListNode* poly2)`: 实现两个多项式的加法,并返回新链表的头节点指针。
   - 创建一个哨兵节点 sentinel 作为新链表的头节点前面的辅助节点。
   - 使用一个指针 tail 指向新链表的尾部节点,初始化为哨兵节点。
   - 使用循环遍历 poly1 和 poly2 两个链表,比较当前节点的指数大小进行处理。
   - 如果 poly1 的指数小于 poly2 的指数,将 poly1 的节点添加到新链表中,并更新 tail 指针和 poly1 指针。
   - 如果 poly1 的指数大于 poly2 的指数,将 poly2 的节点添加到新链表中,并更新 tail 指针和 poly2 指针。
   - 如果 poly1 和 poly2 的指数相等,计算两个系数的和 sum,如果 sum 不为 0,则创建新节点并添加到新链表中,并更新 tail 指针。
   - 循环结束后,将未处理完的节点添加到新链表的尾部。
   - 最后,删除哨兵节点,返回新链表的头节点指针。

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AAA阿魏

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值