1、分别创建两个有序的单链表(每个表的元素个数以及每个元素的值在运行时由键盘输入),现将两个单链表合并,并保证新表依然为有序的单链表。
- #include
- #include
-
- // 定义单链表结构体
- 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
- #include
-
- // 定义单链表结构体
- 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 指针。
- 循环结束后,将未处理完的节点添加到新链表的尾部。
- 最后,删除哨兵节点,返回新链表的头节点指针。