#include <iostream>
#include <random>
using namespace std;
class Node {
public:
int data; //数据
Node* next; //指向下一个节点的指针
Node(int val) :data(val), next(nullptr) {}
};
class LinkedList {
private:
Node* head; //链表头指针
public:
LinkedList() :head(nullptr) {}
//在链表末尾插入节点
void append(int val) {
Node* newNode = new Node(val);
if (!head) { //链表为空
head = newNode;
return;
}
Node* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
}
//在链表头插入节点
void prepend(int val) {
Node* newNode = new Node(val);
newNode->next = head;
head = newNode;
}
//随机产生n个元素的值,并使用头插法插入到链表中
void srendN(int n)
{
//获取高质量的种子
random_device rd;
//生成随机数
mt19937 gen(rd());
//定义随机数分布
uniform_int_distribution<int> intDistribution(1, 100); //生成范围在[1,100]之间的随机数
//生成随机数
int randomInt = intDistribution(gen);
for (int i = 0; i < n; i++) {
Node* newNode = new Node(intDistribution(gen)); //产生100以内的随机数
newNode->next = head;
head = newNode;
}
}
//删除第一个值为val的节点
void deleteNode(int val) {
//链表为空
if (!head)
return;
//第一个节点值为val
if (head->data == val) {
Node* temp = head;
head = head->next;
delete temp;
return;
}
Node* temp = head;
//下一个节点为空,且下一个节点的值不是val
while (temp->next && temp->next->data != val) {
temp = temp->next;
}
//下一个节点的值为val
if (temp->next) {
Node* delNode = temp->next;
temp->next = temp->next->next;
delete delNode;
}
}
//查找是否存在值为val的节点
bool search(int val) const {
Node* temp = head;
while (temp) {
if (temp->data == val)
return true;
temp = temp->next;
}
return false;
}
//反转链表
void reverse()
{
//定义指向当前节点的节点
Node* curr = head;
//定义指向反转后的头节点
Node* rehead = nullptr;
//定义指向当前节点的下一个节点
Node* nextNode;
while (curr) {
//保存下一个节点
nextNode = curr->next;
//断开头节点与下一个节点
curr->next = rehead;
//将rehead置为反转链表的头
rehead = curr;
curr = nextNode;
}
head = rehead;
}
//打印链表
void display() const {
Node* temp = head;
temp = head;
while(temp) {
cout << temp->data << " ";
temp = temp->next;
}
cout << "nullptr" << endl;
}
//释放链表内存
~LinkedList() {
Node* temp;
while (head) {
temp = head;
head = head->next;
delete temp;
}
}
};
int main()
{
LinkedList list;
cout << "使用头插法插入5个元素" << endl;
list.srendN(5);
list.display();
cout << "添加元素20到链表尾端,添加元素10到链表头" << endl;
list.append(20);
list.prepend(10);
list.display();
cout << "查找值为20是否存在链表中" <<endl ;
list.search(20);
cout << "删除值为20的节点" << endl;
list.deleteNode(20);
list.display();
cout << "将链表反转" << endl;
list.reverse();
list.display();
}
使用void reverse()实现链表反转的思路:反转链表就是从头尾节点开始,将首位两边的节点一一对调。
思路:反转就是将第一个节点变为最后一个节点,将第二个节点变为倒数第二个节点,以此类推直到将原链表的尾节点变成反转链表的头节点。也就是:将原链表从头节点开始,依次断开,并从反转后的链表的末尾开始逐个加入断开的节点
如何反转:保存head->next节点,断开head所指向的头节点与它的下一个节点,将head所指向的这个节点作为反转后的链表的最后一个节点。然后将head = head->next;将原来的第二个节点作为链表的首节点。继续保存head的下一个节点到nextNode指针。
重复上面的过程,断开原链表的第二个节点与第三个节点,将第二个节点的next保存原链表的第一个节点,然后再将反转后链表的头指针指向2号节点。这样,就可以实现将原链表从头节点开始,依次断开,并从反转后的链表的末尾开始逐个加入断开的节点,这样就能实现链表的反转。
第二次断开节点

第三次断开节点:

第四次断开节点:

最后一次:

文章介绍了C++中链表类的实现,包括头插法插入节点、在链表头尾插入、随机生成节点、删除指定值节点、查找节点以及链表反转的方法。
1394

被折叠的 条评论
为什么被折叠?



