用C语言编一个程序完成以下三个要求,并解释每行代码的含义。 要求1.先让操作者输入数据元素构造单链表,再让操作者输入m和n的值,将元素值为 m 和 n(如有多个相同元素值, 仅考虑首个出现的元素)的节点建立连接,将元素值为n的节点的链域连到元素值为m的节点后面,将原 来元素值为n的 节点的后续节点移到原来单链表的头部,形成双头相交链表; 要求2. 用环路判断函数(输入为链表头指针)判断链表是否有环路,并使用 2 个不同 的链表头部指针进行查询。 要求3. 将环路链接取消,恢复成单链表,并根据表头指针(输入)求解链表的中间节点(输出中间节点的值并返回指针),且不要将链表转换成数组来求解;
时间: 2024-03-17 21:41:45 浏览: 70
c代码-编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前。如果链表中包含 x,x 只需出现在小于 x 的元素之后(如下所示)。分割元素 x 只需处于“右半部分”即可,其不需要被置于左右两部分之间。
以下是用C语言编写的程序,实现了上述三个要求:
```c
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node {
int val;
struct Node* next;
} Node;
// 构造单链表
Node* createList() {
int val;
Node *head, *p, *q;
head = (Node*) malloc(sizeof(Node));
head->next = NULL;
p = head;
printf("请输入数据元素,以-1结束:\n");
while (1) {
scanf("%d", &val);
if (val == -1) {
break;
}
q = (Node*) malloc(sizeof(Node));
q->val = val;
q->next = NULL;
p->next = q;
p = q;
}
return head;
}
// 建立双头相交链表
void mergeList(Node* head, int m, int n) {
Node *p, *q, *r, *s;
p = head->next;
while (p) {
if (p->val == m) {
q = p;
}
if (p->val == n) {
r = p;
break;
}
p = p->next;
}
if (r == NULL) {
printf("链表中不存在值为%d的节点\n", n);
return;
}
s = r->next;
q->next = r;
r->next = head->next;
head->next = s;
}
// 判断链表是否有环路
int hasCycle(Node* head) {
Node *fast, *slow;
fast = slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
return 1;
}
}
return 0;
}
// 取消链表环路
void cancelCycle(Node* head) {
Node *fast, *slow;
fast = slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
break;
}
}
if (fast == NULL || fast->next == NULL) {
return;
}
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
fast->next = NULL;
}
// 求解链表的中间节点
Node* findMid(Node* head) {
Node *fast, *slow;
fast = slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
int main() {
Node *head, *mid;
int m, n;
head = createList();
printf("请输入m和n的值:\n");
scanf("%d %d", &m, &n);
mergeList(head, m, n);
if (hasCycle(head)) {
printf("链表中存在环路\n");
cancelCycle(head);
printf("已取消链表的环路\n");
} else {
printf("链表中不存在环路\n");
}
mid = findMid(head);
printf("链表的中间节点的值为:%d\n", mid->val);
return 0;
}
```
代码解释:
1. 定义了链表节点结构体 `Node`,其中包含一个整型变量 `val` 和一个指向下一个节点的指针 `next`。
2. 定义了函数 `createList()`,用于构造单链表。首先创建头节点 `head`,然后循环读入数据元素,将每个元素构造成一个新的节点 `q`,并将其插入到链表的末尾。最后返回头节点 `head`。
3. 定义了函数 `mergeList()`,用于建立双头相交链表。首先遍历链表,找到值为 `m` 和 `n` 的节点 `q` 和 `r`,如果找不到值为 `n` 的节点,则直接返回。然后将节点 `r` 的链域连到节点 `q` 后面,将节点 `r` 后面的节点移到链表的头部,即将节点 `r` 的链域指向头节点 `head` 的下一个节点,再将头节点 `head` 的链域指向节点 `s`。
4. 定义了函数 `hasCycle()`,用于判断链表是否有环路。采用快慢指针的方法,如果快指针追上了慢指针,则说明链表有环路;否则,链表没有环路。
5. 定义了函数 `cancelCycle()`,用于取消链表的环路。首先采用快慢指针的方法找到链表中的一个环路,然后再从头节点 `head` 和环路相遇的节点开始,采用两个指针 `slow` 和 `fast` 同时向前遍历,直到它们相遇,此时 `fast` 指向的节点就是环路的尾部节点,将其链域指向空即可。
6. 定义了函数 `findMid()`,用于求解链表的中间节点。同样采用快慢指针的方法,快指针每次走两步,慢指针每次走一步,当快指针走到链表尾部时,慢指针走到的节点就是链表的中间节点。
7. 在主函数 `main()` 中,首先调用 `createList()` 创建单链表,然后读入值 `m` 和 `n`,并调用 `mergeList()` 建立双头相交链表。然后调用 `hasCycle()` 判断链表是否有环路,如果有,则调用 `cancelCycle()` 取消环路;否则,输出链表中不存在环路。最后调用 `findMid()` 求解链表的中间节点,并输出其值。
阅读全文