源码:
#include <iostream>
using namespace std;
// 定义节点类
class Node {
public:
int data; // 数据域
Node* next; // 指针域,指向下一个节点
// 构造函数
Node(int value) {
data = value;
next = nullptr;
}
};
// 定义循环单链表类
class CircularLinkedList {
private:
Node* head; // 指向头节点的指针
public:
// 构造函数
CircularLinkedList() {
head = nullptr;
}
// 在头部插入节点
void insertAtHead(int value)
{
Node* newNode = new Node(value);
if (head == nullptr)
{
head = newNode;
head->next = head; // 自己指向自己,形成循环
}
else
{
Node* temp = head;
while (temp->next != head)
{
temp = temp->next;
}
newNode->next = head;
temp->next = newNode;
head = newNode;
}
}
// 在尾部插入节点
void insertAtTail(int value) {
Node* newNode = new Node(value);
if (head == nullptr) {
head = newNode;
head->next = head;
}
else {
Node* temp = head;
while (temp->next != head) {
temp = temp->next;
}
temp->next = newNode;
newNode->next = head;
}
}
// 删除指定值的节点
void deleteValue(int value)
{
if (head == nullptr)
return;
if (head->data == value)
{
if (head->next == head)
{ // 只有一个节点
delete head;
head = nullptr;
}
else
{
Node* temp = head;
while (temp->next != head)
{
temp = temp->next;
}
Node* toDelete = head;
head = head->next;
temp->next = head;
delete toDelete;
}
return;
}
Node* current = head;
while (current->next != head && current->next->data != value)
{
current = current->next;
}
if (current->next->data == value)
{
Node* toDelete = current->next;
current->next = toDelete->next;
delete toDelete;
}
}
// 修改指定位置的节点值
void updateValue(int position, int newValue)
{
if (head == nullptr)
return;
Node* current = head;
int count = 1;
while (count != position && current->next != head)
{
current = current->next;
count++;
}
if (count == position)
{
current->data = newValue;
}
}
// 查找指定值的节点
bool searchValue(int value)
{
if (head == nullptr) return false;
Node* current = head;
do
{
if (current->data == value)
{
return true;
}
current = current->next;
} while (current != head);
return false;
}
// 打印链表
void printList() const
{
if (head == nullptr) return;
Node* current = head;
do
{
cout << current->data << " ";
current = current->next;
} while (current != head);
cout << endl;
}
// 链表逆置
void reverseList()
{
if (head == nullptr || head->next == head) return;
Node* prev = nullptr;
Node* current = head;
Node* next = nullptr;
Node* tail = head;
do
{
next = current->next;
current->next = prev;
prev = current;
current = next;
} while (current != head);
head->next = prev;
head = prev;
}
// 析构函数,释放链表内存
~CircularLinkedList()
{
if (head == nullptr) return;
Node* current = head;
while (current->next != head)
{
Node* toDelete = current;
current = current->next;
delete toDelete;
}
delete current;
head = nullptr;
}
};
// 主函数
int main()
{
CircularLinkedList list;
int choice, value, position;
while (true)
{
cout << "1. 在头部插入节点" << endl;
cout << "2. 在尾部插入节点" << endl;
cout << "3. 删除节点" << endl;
cout << "4. 修改节点" << endl;
cout << "5. 查找节点" << endl;
cout << "6. 打印链表" << endl;
cout << "7. 逆置链表" << endl;
cout << "8. 退出" << endl;
cout << "请输入你的选择: ";
cin >> choice;
switch (choice) {
case 1:
cout << "请输入要插入的值: ";
cin >> value;
list.insertAtHead(value);
system("pause");
system("cls");
break;
case 2:
cout << "请输入要插入的值: ";
cin >> value;
list.insertAtTail(value);
system("pause");
system("cls");
break;
case 3:
cout << "请输入要删除的值: ";
cin >> value;
list.deleteValue(value);
system("pause");
system("cls");
break;
case 4:
cout << "请输入要修改的位置和新值: ";
cin >> position >> value;
list.updateValue(position, value);
system("pause");
system("cls");
break;
case 5:
cout << "请输入要查找的值: ";
cin >> value;
if (list.searchValue(value)) {
cout << "找到节点: " << value << endl;
}
else {
cout << "未找到节点: " << value << endl;
}
system("pause");
system("cls");
break;
case 6:
list.printList();
system("pause");
system("cls");
break;
case 7:
list.reverseList();
cout << "链表已逆置。" << endl;
system("pause");
system("cls");
break;
case 8:
return 0;
default:
cout << "无效选择,请重试。" << endl;
}
}
system("pause");
return 0;
}
关于元素逆置
链表逆置的目标是将链表中所有节点的指针方向反转。例如,给定一个链表:
head -> 0x001(1, 0x002) -> 0x002(2, 0x003) -> 0x003(3, 0x001)
逆置后的链表应该变成:
head -> 0x003(3, 0x002) -> 0x002(2, 0x001) -> 0x001(1, 0x003)
核心思路
逆置链表的核心在于逐个改变每个节点的 `next` 指针,使其指向前一个节点。为了实现这一点,我们需要:
1. 遍历链表。
2. 记录当前节点的前一个节点和下一个节点。
3. 更新当前节点的 `next` 指针。
使用的指针
prev:记录前一个节点的位置。初始值为 `nullptr`,因为第一个节点逆置后将成为新链表的尾节点,它的 next 应为 nullptr。
current:记录当前节点,从头节点开始逐个遍历链表。
next:临时保存当前节点的下一个节点的位置,以便在改变 `current->next` 后还能继续遍历链表。
tail:保存原始链表的头节点,在逆置完成后更新新链表的末尾节点指向新头节点,实现循环。