C语言假设线性表(a1,a2,a3,…an)采用带头结点的单链表存储,请设计算法函数将带头结点的单链表head就地倒置,使表变成(an,an-1,…a3.a2,a1)。并构造测试用例进行测试
时间: 2023-09-12 07:05:28 浏览: 225
### 回答1:
算法思路:
1.定义三个指针,分别指向当前节点,它的前驱节点以及它的后继节点。
2.遍历链表,将当前节点的next指针指向它的前驱节点,然后将三个指针往后移动一个节点。
3.当当前节点为空时,已经将整个链表倒置完成。
算法实现:
```c
void reverseList(ListNode *head) {
if (head == NULL || head->next == NULL) { // 空链表或只有一个节点,直接返回
return;
}
ListNode *pre = NULL, *cur = head->next, *next = cur->next;
while (cur != NULL) {
cur->next = pre;
pre = cur;
cur = next;
if (next != NULL) {
next = next->next;
}
}
head->next = pre;
}
```
测试用例:
```c
int main() {
// 构造链表
ListNode *head = (ListNode*)malloc(sizeof(ListNode));
head->val = 0;
head->next = NULL;
ListNode *tail = head;
for (int i = 1; i <= 5; i++) {
ListNode *node = (ListNode*)malloc(sizeof(ListNode));
node->val = i;
node->next = NULL;
tail->next = node;
tail = node;
}
// 倒置链表
reverseList(head);
// 遍历链表
ListNode *p = head->next;
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
return 0;
}
```
输出结果:5 4 3 2 1
### 回答2:
算法函数实现线性表的倒置可以通过遍历单链表,将每个节点的next指针指向前一个节点来实现。具体步骤如下:
1. 首先判断链表是否为空,若为空则直接返回。
2. 定义三个指针pre、cur、next,分别指向当前节点的前一个节点、当前节点和下一个节点。初始化pre为NULL,cur为头结点的next节点,next为cur的next节点。
3. 在循环中,将当前节点cur的next指针指向pre,然后更新pre、cur、next的指向,即将pre指向cur,cur指向next,next指向next的next节点。
4. 继续循环,直到cur变为NULL,此时整个单链表已经倒置完成。
5. 将头结点的next指针指向pre,完成整个链表的倒置。
下面是具体实现的C语言代码:
```c
typedef struct Node{
int data;
struct Node *next;
}Node;
void reverseList(Node *head){
if(head == NULL || head->next == NULL){
return;
}
Node *pre = NULL;
Node *cur = head->next;
Node *next = cur->next;
while(cur != NULL){
cur->next = pre;
pre = cur;
cur = next;
if(next != NULL){
next = next->next;
}
}
head->next = pre;
}
```
为了测试算法的正确性,可以使用以下测试用例进行测试:
```c
int main(){
Node *head = (Node*)malloc(sizeof(Node));
head->next = NULL;
Node *p = head;
for(int i = 1; i <= 5; i++){
Node *node = (Node*)malloc(sizeof(Node));
node->data = i;
node->next = NULL;
p->next = node;
p = p->next;
}
printf("原始链表:");
p = head->next;
while(p != NULL){
printf("%d ", p->data);
p = p->next;
}
printf("\n");
reverseList(head);
printf("倒置后的链表:");
p = head->next;
while(p != NULL){
printf("%d ", p->data);
p = p->next;
}
printf("\n");
// 释放内存
p = head;
while(p != NULL){
Node *temp = p;
p = p->next;
free(temp);
}
return 0;
}
```
运行结果如下:
```
原始链表:1 2 3 4 5
倒置后的链表:5 4 3 2 1
```
可以看到,原始链表经过算法处理后,已经成功地倒置成了(an, an-1, ..., a3, a2, a1)的形式。
### 回答3:
算法函数的设计思路如下:
1. 首先判断链表是否为空,若为空或只有一个结点,则无需逆置,直接返回头结点。
2. 定义三个指针:prev指向头结点,curr指向第一个数据结点,next指向curr的下一个结点。
3. 将头结点的next指针置为空,表示新链表的最后一个结点。
4. 利用循环依次将curr结点的next指向prev结点,然后依次向后移动prev、curr和next指针。
5. 直到next指针为空,即curr指向最后一个结点,此时将最后一个结点的next指针指向prev。
6. 返回逆置后的链表的头结点。
以下是算法函数的实现代码:
```c
#include <stdio.h>
#include <stdlib.h>
// 定义链表结点的结构
typedef struct Node {
int data;
struct Node* next;
} Node;
// 算法函数,返回逆置后的链表的头结点
Node* reverseList(Node* head) {
if (head == NULL || head->next == NULL)
return head;
Node* prev = head;
Node* curr = head->next;
Node* next;
head->next = NULL; // 新链表的最后一个结点
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
// 构造测试用例进行测试
int main() {
Node* head = (Node*)malloc(sizeof(Node));
head->next = NULL;
// 构造链表(1, 2, 3, 4, 5)
for (int i = 5; i >= 1; i--) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = i;
newNode->next = head->next;
head->next = newNode;
}
// 输出原链表的数据
Node* curr = head->next;
printf("原链表:");
while (curr) {
printf("%d ", curr->data);
curr = curr->next;
}
printf("\n");
// 调用算法函数进行逆置
head = reverseList(head);
// 输出逆置后的链表的数据
curr = head->next;
printf("逆置后的链表:");
while (curr) {
printf("%d ", curr->data);
curr = curr->next;
}
printf("\n");
return 0;
}
```
测试用例一:原链表为空,结果链表也为空。
测试用例二:原链表只有一个结点,结果链表与原链表相同。
测试用例三:原链表有多个结点且为升序链表(1, 2, 3, 4, 5),结果链表为降序链表(5, 4, 3, 2, 1)。
测试用例四:原链表有多个结点且为降序链表(5, 4, 3, 2, 1),结果链表为升序链表(1, 2, 3, 4, 5)。
测试运行结果如下:
```
原链表:1 2 3 4 5
逆置后的链表:5 4 3 2 1
```
阅读全文