题目描述
用C++实现含头结点的单链表,然后实现单链表的两个结点交换位置。
注意不能简单交换两个结点包含数据,必须通过修改指针来实现两个结点的位置交换
交换函数定义可以参考:
swap(int pa, int pb) //pa和pb表示两个结点在单链表的位置序号
swap (ListNode * p, ListNode * q) //p和q表示指向两个结点的指针
输入
第1行先输入n表示有n个数据,接着输入n个数据
第2行输入要交换的两个结点位置
第3行输入要交换的两个结点位置
输出
第一行输出单链表创建后的所有数据,数据之间用空格隔开
第二行输出执行第1次交换操作后的单链表数据,数据之间用空格隔开
第三行输出执行第2次交换操作后的单链表数据,数据之间用空格隔开
如果发现输入位置不合法,输出字符串error,不必输出单链表
输入样例
5 11 22 33 44 55
1 4
2 6
输出样例
11 22 33 44 55
44 22 33 11 55
error
struct ListNode 定义结构体
是为了表示链表中的每一个结点
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
- int val:链表的每个节点都需要存储一个数据元素
- ListNode* next:是一个指针。指向链表中的下一个节点。通过它,将多个节点连接起来形成链表
- ListNode(int x) : val(x), next(nullptr):构造函数,用于初始化ListNode中的变量val,next
val(x):将传入的参数 x 赋值给结点的 val 成员变量。
next(nullptr):将指针 next 初始化为 nullptr(空指针),表明该结点当前没有指向下一个结点。
构造函数让创建结点的过程变得简洁。例如,当你写 new ListNode(data) 时,它会自动调用这个构造函数来初始化结点的值和指针。
ListNode* createList(int n) 创建一个包含n个元素的单链表
ListNode* createList(int n) {
ListNode* head = new ListNode(0);
ListNode* tail = head;
for (int i = 0; i < n; i++) {
int data;
cin >> data;
tail->next = new ListNode(data); // 添加新结点
tail = tail->next;
}
return head;
}
- ListNode* head = new ListNode(0):创建头结点,赋予初始值(可帮助区分头结点和其他结点),head 指向这个头结点
- ListNode* tail = head:追踪当前链表的尾部,方便在尾部添加新结点
- tail->next = new ListNode(data):添加新结点到链表尾部。tail->next指向新创建的结点
- tail = tail->next:移动到链表的最后一个结点,即刚刚创建的结点。通过不断循环,新结点继续添加到链表的尾部
- return head:链表创建完成,返回链表的头结点指针
创建完后,返回一个指向单链表头结点的指针,返回类型是 ListNode*
单链表的结构是由一系列结点通过指针连接在一起的。每个结点只知道它的下一个结点在哪里。因此,如果你想访问整个链表,必须从头结点开始
返回 head 以后,实际的链表数据从head->next 开始
void printList(ListNode* head) 输出单链表
void printList(ListNode* head) {
ListNode* current = head->next;
while (current) {
cout << current->val << " ";
current = current->next;
}
cout << endl;
}
- ListNode* head:接收链表的头结点
- ListNode* current = head->next:链表的第一个存储数据的结点
bool swapNodes(ListNode* head, int pos1, int pos2) 交换两个结点的位置
bool swapNodes(ListNode* head, int pos1, int pos2) {
if (pos1 == pos2) return true; // 如果两个位置相同,不需交换
ListNode* prev1 = nullptr, * prev2 = nullptr, * node1 = head, * node2 = head;
// 查找第一个位置的结点及其前驱
for (int i = 0; i < pos1 && node1; i++) {
prev1 = node1;
node1 = node1->next;
}
// 查找第二个位置的结点及其前驱
for (int i = 0; i < pos2 && node2; i++) {
prev2 = node2;
node2 = node2->next;
}
// 如果有任何一个位置越界,则返回false,交换失败
if (!node1 || !node2) return false;
// 如果两个位置都有效,进行交换
prev1->next = node2;
prev2->next = node1;
// 交换 next 指针
ListNode* temp = node1->next;
node1->next = node2->next;
node2->next = temp;
return true;
}
- 初始化四个指针变量:pre1,pre2存储要交换的两个结点的前驱结点,初始为nullptr,node1,node2存储要交换的两个结点,初始为头结点
- 两个for循环:找到序号为pos1,pos2的结点以及它们的前驱结点。
如果输入的位置序号 pos1 或 pos2 超出了链表的实际长度,那么在遍历链表时,node1 或 node2 将会变成 nullptr。在这种情况下,如果不检查 node1 和 node2 是否为 nullptr,那么在尝试交换结点时就会出现问题
- prev1->next = node2:更新前驱结点的next指针,以指向新结点的位置
- node1->next = node2->next:交换两个结点的next指针
完整代码
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) :val(x), next(nullptr){}
};
ListNode* List(int n) {
ListNode* head = new ListNode(0);
ListNode* tail = head;
for (int i = 0; i < n; ++i) {
int num;
cin >> num;
tail->next = new ListNode(num);
tail = tail->next;
}
return head;
}
void printList(ListNode* head) {
ListNode* current = head->next;
while (current) {
cout << current->val << ' ';
current = current->next;
}
cout << endl;
}
bool SwapNode(ListNode* head, int pos1, int pos2) {
if (pos1 == pos2)return true;
ListNode* f1 = nullptr, * f2 = nullptr, * node1 = head, * node2 = head;
//找到前结点和当前结点
for (int i = 0; i < pos1&&node1; ++i) {
f1 = node1;
node1 = node1->next;
}
for (int i = 0; i < pos2&&node2; ++i) {
f2 = node2;
node2 = node2->next;
}
//如果越界
if (!node1 || !node2)return false;
f1->next = node2;
f2->next = node1;
ListNode* tep = node1->next;
node1->next = node2->next;
node2->next = tep;
return true;
}
void deleteList(ListNode* head) {
ListNode* current = head;
while (current) {
ListNode* next = current->next;
delete current;
current = next;
}
}
int main() {
int n;
cin >> n;
ListNode* head = List(n);
printList(head);
int p1, p2;
cin >> p1 >> p2;
if (!SwapNode(head, p1, p2)) {
cout << "error\n";
return 0;
}
printList(head);
cin >> p1 >> p2;
if (!SwapNode(head, p1, p2)) {
cout << "error\n";
return 0;
}
printList(head);
deleteList(head);
return 0;
}