使用C++创建链表,并实现节点插入、删除、查找以及链表反转的基本功能

文章介绍了C++中链表类的实现,包括头插法插入节点、在链表头尾插入、随机生成节点、删除指定值节点、查找节点以及链表反转的方法。
摘要由CSDN通过智能技术生成
#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号节点。这样,就可以实现将原链表从头节点开始,依次断开,并从反转后的链表的末尾开始逐个加入断开的节点,这样就能实现链表的反转。

        第二次断开节点

第三次断开节点:

第四次断开节点:

最后一次:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值