【C++】list讲解及模拟

目录

list的基本介绍

list模拟实现

一.创建节点

二.迭代器

1.模版参数

2.迭代器的实现:

a. !=

b. ==

c. ++ --

d. *指针

e.&引用

整体iterator (与const复用):

三.功能实现

1.模版参数

2.具体功能实现:

2.1 构造函数

2.2 begin() && end()

2.3插入

insert任意位置插入

push_back 尾插&& push_front前插

2.4 删除

erase任意位置删除

pop_back 头删 && pop_front尾删

2.5 拷贝构造 && 赋值操作符

2.6 clear() && 析构函数

代码示例

Test.cpp

list.h


list的基本介绍

list本质上是一个带头双向循环链表,列表是一种用于存储一组元素的数据结构,元素按照插入的顺序排列。它允许动态地添加和删除元素,可以重复存储相同的值。列表提供了对元素的插入、删除、访问和遍历等常用操作。

列表是序列容器,允许在序列内的任何位置插入和擦除操作,并在两个方向上进行迭代。

列表容器被实现为双链接列表;双链接列表可以将它们所包含的每个元素存储在不同的和不相关的存储位置中。顺序通过与前面元素的链接和后面元素的链接的关联在内部保持。

与其他序列容器相比,列表和前向列表的主要缺点是它们无法通过位置直接访问元素; 例如,要访问列表中的第六个元素,必须从已知位置(如开始或结束)迭代到该位置,该位置之间的距离需要线性时间。它们还会消耗一些额外的内存来保持与每个元素相关联的链接信息(这可能是大量小元素列表的一个重要因素)。

若要查看双向循环链表相关知识→:数据结构:线性表之-循环双向链表(万字详解)_数据结构循环双链表概念-CSDN博客

list模拟实现

一.创建节点

template <class T>//模版
struct list_node
{
    list_node<T> *_prev;//前一节点
    list_node<T> *_next;//后一节点
    T _data;
​
    // 构造函数,创建链表
    list_node(const T &x = T()) // 用匿名对象做缺省值(调用默认构造),以存储其他类型的元素
        : _next(nullptr), _prev(nullptr), _data(x)
    {}
};

二.迭代器

1.模版参数

template <class T, class Ref, class Ptr>
  1. class T:表示元素类型,为了应对要接收不同类型的数据

  2. class Ref:引用类型参数模版,Ref用于提供对迭代器所指向元素的引用

  3. class Ptr:指针类型参数模版,Ptr用于提供对迭代器所指向元素的指针。

后面会提到Ref,Ptr作用,请仔细阅读哦

2.迭代器的实现:

基本模版:

template <class T, class Ref, class Ptr>
struct __list_iterator
{
  //重新命名
  typedef list_node<T> node; 
  typedef __list_iterator<T, Ref, Ptr> self;
  
  node *_node;//指向列表节点的指针,用于追踪迭代器的当前位置。
​
  //构造函数,接受一个指向列表节点的指针,并将其作为初始位置给 _node。
  __list_iterator(node *n)
      : _node(n)
  {}
};

这个结构体的作用是提供列表的迭代功能,它可以被用于遍历列表中的元素,并对元素进行访问和操作。

"const T&"表示迭代器所指向元素的引用类型,而"const T*"表示迭代器所指向元素的指针类型。 这样定义迭代器的目的是为了在const成员函数中使用该迭代器,并保证在遍历列表时不会修改列表中的元素"

参考:

list<int>::iterator it = lt.begin();
//__list_itreator后续被重命名为iterator
a. !=
bool operator!=(const self &s)
{
    return _node != s._node;
}
b. ==
bool operator==(const self &s)
{
    return _node == s._node;
}
c. ++ --
self &operator++()
{
    _node = _node->_next;
    return *this;
}
self &operator++(int)// 后置++
{
    self tmp = *this;
    _node = _node->_next;
    return tmp;
}
​
self &operator--()
{
    _node = _node->_prev;
    return *this;
}
self &operator--(int) // 后置--
{
    self tmp = *this;
    _node = _node->_prev;
    return tmp;
}
d. *指针

重载了解引用运算符(*),返回 _node->_data 的引用,即迭代器所指向的元素

Ref &operator*()//加const不能修改数据
{
    return _node->_data;
}
e.&引用

重载了箭头运算符(->),返回 _node->_data 的指针,即迭代器所指向元素的指针

Ptr operator->()
{
    return &(_node->_data); // 取地址
}

Ref与Ptr的定义在class list中进行定义

整体iterator (与const复用):
template <class T, class Ref, class Ptr>
struct __list_iterator
{
    typedef list_node<T> node;
    typedef __list_iterator<T, Ref, Ptr> self;
    node *_node;

    __list_iterator(node *n)
        : _node(n)
    {
    }

    Ref &operator*()
    {
        return _node->_data;
    }

    Ptr operator->()
    {
        return &(_node->_data); // 取地址
    }

    self &operator++()
    {
        _node = _node->_next;
        return *this;
    }
    self &operator++(int)
    {
        self tmp = *this;
        _node = _node->_next;
        return tmp;
    }

    self &operator--()
    {
        _node = _node->_prev;
        return *this;
    }
    self &operator--(int) // 后置--
    {
        self tmp = *this;
        _node = _node->_prev;
        return tmp;
    }

    bool operator!=(const self &s)
    {
        return _node != s._node;
    }

    bool operator==(const self &s)
    {
        return _node == s._node;
    }
};

三.功能实现

1.模版参数

    
template <class T>
class list
{
    typedef list_node<T> node;

public:
    //iterator和const_iterator都是公用接口
    typedef __list_iterator<T, T &, T *> iterator;
    typedef __list_iterator<T, const T &, const T *> const_iterator;

private:
    //头节点
    node *_head; // ListNode<T>是类型 , ListNode是类名
};

2.具体功能实现:

2.1 构造函数

为了后续操作的方便,将初始化链表代码写在另一个函数里

void empty_init()
{
    _head = new node;
    _head->_next = _head;
    _head->_prev = _head;
}
list()
{
    empty_init();
}
2.2 begin() && end()
iterator begin()
{
    return iterator(_head->_next);
}
​
iterator end()
{
    return iterator(_head);
}
​
const_iterator begin() const
{
    return const_iterator(_head->_next);
}
​
const_iterator end() const
{
    return const_iterator(_head);
}

test:通过迭代器依次打印出元素

list<int>::iterator it = lt.begin();
while (it != lt.end())
{
    cout << *it << " ";
    ++it;
}
cout << endl;

我们将迭代器遍历封装到一个函数内:

void print_list(const list<T> &lt)
{
    cout << "---list---" << endl;
    // list<int>::const_iterator it = lt.begin();
    list<int>::const_iterator it = lt.begin();
    while (it != lt.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl
         << "---list---" << endl;
}
2.3插入
insert任意位置插入
void insert(iterator pos, const T &x)
{
    node *cur = pos._node;   // .访问pos内的成员变量_node
    node *prev = cur->_prev; // ->访问指针所指向的节点的成员
​
    node *new_node = new node(x);
​
    prev->_next = new_node;
    new_node->_prev = prev;
    new_node->_next = cur;
    cur->_prev = new_node;
}
push_back 尾插&& push_front前插
void push_back(const T &x)
{
    insert(end(), x);
}
void push_front(const T &x)
{
    insert(begin(), x);
}

test:

void test_list3()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
​
    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
​
    it = lt.begin();
    list<int>::iterator pos = lt.begin();
    ++pos;
    lt.insert(pos, 20);
​
    lt.print_list(lt);
​
    cout << endl;
}
2.4 删除
erase任意位置删除
iterator erase(iterator pos)
{
    assert(pos != end());
​
    node *prev = pos._node->_prev;
    node *next = pos._node->_next;
​
    prev->_next = next;
    next->_prev = prev;
    delete pos._node;
​
    return iterator(next);
}
pop_back 头删 && pop_front尾删
void pop_back()
{
    erase(--end());
}
void pop_front()
{
    erase(begin());
}

test:

void test_list4()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.print_list(lt);
    cout << endl;
    lt.push_back(100);
    lt.push_front(99);
    lt.print_list(lt);
    cout << endl;
​
    lt.pop_back();
    lt.pop_front();
    lt.print_list(lt);
    cout << endl;
}

2.5 拷贝构造 && 赋值操作符

swap交换函数:

void swap(list<T> &temp)
{
    std::swap(_head, temp._head);
}

当调用swap函数时[例子:lt2拷贝lt1调用swap时],调用拷贝构造将lt1进行拷贝再交换到lt2

list:

list(const list<T> &lt)
{
    empty_init();//创建头节点
    list<T> temp(lt.begin(), lt.end());
    swap(temp);
}

赋值操作数:

// lt3=lt2
// 不能使用&,而是传值调用拷贝构造,拷贝lt2,赋值给lt3
list<T> &operator=(const list<T> lt)//const list<T>& lt
{
    swap(lt);
    return *this;
}

test:

void test_list6()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.print_list(lt);
    cout << endl;
​
    // list<int> lt2(lt);
    // lt2.print_list(lt2);
    // cout << endl;
    list<int> lt2 = lt;
    lt2.print_list(lt2);
    lt.print_list(lt);
}

2.6 clear() && 析构函数

clear:清除头节点以外的数据

void clear()
{
    iterator it = begin();
    while (it != end())
        it = erase(it); // erase(it++);//后置++返回的是前一个的拷贝,不会失效
}

test:

void test_list5()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.print_list(lt);
    cout << endl;
​
    lt.clear();
    lt.push_back(20);
​
    lt.print_list(lt);
}

析构:

~list()
{
    clear();
    delete _head;
    _head = nullptr;
}

代码示例

Test.cpp

#include "list.h"

int main()
{
    wzf::test_list6();

    return 0;
}

list.h

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

namespace wzf
{
    // 节点
    template <class T>
    struct list_node
    {
        list_node<T> *_prev;
        list_node<T> *_next;
        T _data;

        // 构造函数,创建链表
        list_node(const T &x = T()) // 用匿名对象做缺省值(调用默认构造),以存储收其他类型的元素
            : _next(nullptr), _prev(nullptr), _data(x)
        {
        }
    };

    // 迭代器
    // // 1.iterator
    // template <class T>
    // struct __list_iterator
    // {
    //     typedef list_node<T> node;
    //     typedef __list_iterator<T> self;
    //     node *_node;

    //     __list_iterator(node *n)
    //         : _node(n)
    //     {
    //     }

    //     T &operator*()
    //     {
    //         return _node->_data;
    //     }

    //     self &operator++()
    //     {
    //         _node = _node->_next;
    //         return *this;
    //     }
    //     self &operator++(int) // 后置++
    //     {
    //         self tmp = *this;
    //         _node = _node->_next;
    //         return tmp;
    //     }

    //     self &operator--()
    //     {
    //         _node = _node->_prev;
    //         return *this;
    //     }
    //     self &operator--(int)
    //     {
    //         self tmp = *this;
    //         _node = _node->_prev;
    //         return tmp;
    //     }

    //     bool operator!=(const self &s)
    //     {
    //         return _node != s._node;
    //     }

    //     bool operator==(const self &s)
    //     {
    //         return _node == s._node;
    //     }
    // };
    // // 2.const_iterator
    // template <class T>
    // struct __list_const_iterator
    // {
    //     typedef list_node<T> node;
    //     typedef __list_const_iterator<T> self;
    //     node *_node;

    //     __list_const_iterator(node *n)
    //         : _node(n)
    //     {
    //     }

    //     const T &operator*() // 与1区别的地方,加const不能修改数据
    //     {
    //         return _node->_data;
    //     }

    //     self &operator++()
    //     {
    //         _node = _node->_next;
    //         return *this;
    //     }
    //     self &operator++(int) // 后置++
    //     {
    //         self tmp = *this;
    //         _node = _node->_next;
    //         return tmp;
    //     }

    //     self &operator--()
    //     {
    //         _node = _node->_prev;
    //         return *this;
    //     }
    //     self &operator--(int)
    //     {
    //         self tmp = *this;
    //         _node = _node->_prev;
    //         return tmp;
    //     }

    //     bool operator!=(const self &s)
    //     {
    //         return _node != s._node;
    //     }

    //     bool operator==(const self &s)
    //     {
    //         return _node == s._node;
    //     }
    // };

    // template <class T,class Ref>
    // struct __list_iterator
    // {
    //     typedef list_node<T> node;
    //     typedef __list_iterator<T,Ref> self;
    //     node *_node;

    //     __list_iterator(node *n)
    //         : _node(n)
    //     {
    //     }

    //     Ref &operator*()
    //     {
    //         return _node->_data;
    //     }

    //     self &operator++()
    //     {
    //         _node = _node->_next;
    //         return *this;
    //     }
    //     self &operator++(int)
    //     {
    //         self tmp = *this;
    //         _node = _node->_next;
    //         return tmp;
    //     }

    //     self &operator--()
    //     {
    //         _node = _node->_prev;
    //         return *this;
    //     }
    //     self &operator--(int) // 后置++
    //     {
    //         self tmp = *this;
    //         _node = _node->_prev;
    //         return tmp;
    //     }

    //     bool operator!=(const self &s)
    //     {
    //         return _node != s._node;
    //     }

    //     bool operator==(const self &s)
    //     {
    //         return _node == s._node;
    //     }
    // };
    // 迭代器
    template <class T, class Ref, class Ptr>
    struct __list_iterator
    {
        typedef list_node<T> node;
        typedef __list_iterator<T, Ref, Ptr> self;
        node *_node;

        __list_iterator(node *n)
            : _node(n)
        {
        }

        Ref &operator*()
        {
            return _node->_data;
        }

        Ptr operator->()
        {
            return &(_node->_data); // 取地址
        }

        self &operator++()
        {
            _node = _node->_next;
            return *this;
        }
        self &operator++(int)
        {
            self tmp = *this;
            _node = _node->_next;
            return tmp;
        }

        self &operator--()
        {
            _node = _node->_prev;
            return *this;
        }
        self &operator--(int) // 后置--
        {
            self tmp = *this;
            _node = _node->_prev;
            return tmp;
        }

        bool operator!=(const self &s)
        {
            return _node != s._node;
        }

        bool operator==(const self &s)
        {
            return _node == s._node;
        }
        /*
        "const T&"表示迭代器所指向元素的引用类型,
        而"const T*"表示迭代器所指向元素的指针类型。
        这样定义迭代器的目的是为了在const成员函数中
        使用该迭代器,并保证在遍历列表时不会修改列表中的元素
        */
    };
    template <class T>
    class list
    {
        typedef list_node<T> node;

    public:
        typedef __list_iterator<T, T &, T *> iterator;
        typedef __list_iterator<T, const T &, const T *> const_iterator;
        // typedef __list_const_iterator<T> const_iterator;

        iterator begin()
        {
            return iterator(_head->_next);
        }

        iterator end()
        {
            return iterator(_head);
        }

        const_iterator begin() const
        {
            return const_iterator(_head->_next);
        }

        const_iterator end() const
        {
            return const_iterator(_head);
        }

        void empty_init()
        {
            _head = new node;
            _head->_next = _head;
            _head->_prev = _head;
        }
        list()
        {
            empty_init();
        }

        // 构造函数, 迭代器区间
        template <class Iterator>
        list(const Iterator first, const Iterator last)
        {
            empty_init(); // 创建头节点
            for (Iterator it = first; it != last; ++it)
                push_back(*it);
        }

        void swap(list<T> &temp)
        {
            std::swap(_head, temp._head);
        }
        // 拷贝构造
        // lt2(lt1)
        // list(const list<T> &lt)
        // {
        //     empty_init();
        //     const_iterator it = lt.begin();
        //     while (it != lt.end())
        //     {
        //         push_back(*it);
        //         ++it;
        //     }
        // }
        list(const list<T> &lt)
        {
            empty_init();
            list<T> temp(lt.begin(), lt.end());
            swap(temp);
        }

        // 赋值操作符
        // lt3=lt2
        // 不能使用&,而是传值调用拷贝构造,拷贝lt2,赋值给lt3
        list<T> &operator=(const list<T> lt)
        {
            swap(lt);
            return *this;
        }

        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }

        // 清除头节点以外的数据
        void clear()
        {
            iterator it = begin();
            while (it != end())
                it = erase(it); // erase(it++);//后置++返回的是前一个的拷贝,不会失效
        }

        // void push_back(const T &x)
        // {
        //     node *tail = _head->_prev;
        //     node *new_node = new node(x);

        //     tail->_next = new_node;
        //     new_node->_prev = tail;
        //     new_node->_next = _head;
        //     _head->_prev = new_node;
        // }
        void push_back(const T &x)
        {
            insert(end(), x);
        }
        void push_front(const T &x)
        {
            insert(begin(), x);
        }

        void pop_back()
        {
            erase(--end());
        }
        void pop_front()
        {
            erase(begin());
        }

        void print_list(const list<T> &lt)
        {
            cout << "---list---" << endl;
            // list<int>::const_iterator it = lt.begin();
            list<int>::const_iterator it = lt.begin();
            while (it != lt.end())
            {
                cout << *it << " ";
                ++it;
            }
            cout << endl
                 << "---list---" << endl;
        }

        void insert(iterator pos, const T &x)
        {
            node *cur = pos._node;   // .访问pos内的成员变量_node
            node *prev = cur->_prev; // ->访问指针所指向的节点的成员

            node *new_node = new node(x);

            prev->_next = new_node;
            new_node->_prev = prev;
            new_node->_next = cur;
            cur->_prev = new_node;
        }

        iterator erase(iterator pos)
        {
            assert(pos != end());

            node *prev = pos._node->_prev;
            node *next = pos._node->_next;

            prev->_next = next;
            next->_prev = prev;
            delete pos._node;

            return iterator(next);
        }
        /*
        在该函数的最后一行,返回了一个迭代器对象 `iterator(next)`。
        这是因为在 C++ STL 中,通常情况下,删除一个元素后,我们希望返回
        删除元素的下一个位置作为新的迭代器。直接返回 `next` 的话,可能会
        暴露内部实现细节,使得用户可以直接操作指针 `next`,可能导致潜在的问题。
        为了隐藏底层指针的细节,通常会将其封装在迭代器对象中返回。因此
        ,返回 `iterator(next)` 的方式可以提供更好的封装性和安全性,
        使用户能够使用迭代器对象来操作返回的下一个位置,而不需要直接访问底层的指针。
        这也符合 C++ STL 设计的一般原则,即通过迭代器提供统一的接口,隐藏底层的具体实现细节。
        */

    private:
        node *_head; // ListNode<T>是类型 , ListNode是类名
    };
    void test_list1()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);

        list<int>::iterator it = lt.begin();
        while (it != lt.end())
        {
            cout << *it << " ";
            ++it;
        }
        cout << endl;
        lt.print_list(lt);
    }

    struct AA
    {
        int _a1;
        int _a2;

        AA(int a1 = 0, int a2 = 0)
            : _a1(a1), _a2(a2)
        {
        }
    };
    void test_list2()
    {
        list<AA> lt;
        lt.push_back(AA(1, 2));
        lt.push_back(AA(3, 4));
        lt.push_back(AA(5, 6));

        list<AA>::iterator it = lt.begin();
        while (it != lt.end())
        {
            cout << it->_a1 << " " << it._node->_data._a2 << endl;
            cout << it.operator->()->_a1 << " " << it.operator->()->_a2 << endl;
            cout << it.operator->() << endl
                 << endl; // 地址值
            ++it;
        }
    }

    void test_list3()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);

        list<int>::iterator it = lt.begin();
        while (it != lt.end())
        {
            cout << *it << " ";
            ++it;
        }
        cout << endl;

        it = lt.begin();
        list<int>::iterator pos = lt.begin();
        ++pos;
        lt.insert(pos, 20);

        lt.print_list(lt);

        cout << endl;
    }

    void test_list4()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.print_list(lt);
        cout << endl;
        lt.push_back(100);
        lt.push_front(99);
        lt.print_list(lt);
        cout << endl;

        lt.pop_back();
        lt.pop_front();
        lt.print_list(lt);
        cout << endl;
    }

    void test_list5()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.print_list(lt);
        cout << endl;

        lt.clear();
        lt.push_back(20);

        lt.print_list(lt);
    }

    void test_list6()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.print_list(lt);
        cout << endl;

        // list<int> lt2(lt);
        // lt2.print_list(lt2);
        // cout << endl;
        list<int> lt2 = lt;
        lt2.print_list(lt2);
        lt.print_list(lt);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349885.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【oracle】oracle客户端及oracle连接工具

一、关于oracle客户端 1.1 Oracle Client 完整客户端 包含完整的客户端连接工具。 包很大&#xff0c;需要安装 1.2 instantclient 即时客户端 是 Oracle(R) 发布的轻量级数据库客户端&#xff0c;减少甚至只包含几个文件&#xff0c;您无需安装标准的客户端&#xff0c;就可以…

Element UI样式修改之NavMenu导航菜单箭头样式修改

UI设计稿给的菜单箭头样式可能与我们饿了么组件NavMenu的菜单箭头样式不一致,目前我们侧边导航菜单的上下翻转箭头如下所示: 希望得到如下的结果: 找到饿了么Icon里我们想要向下箭头,F12后复制content内容content: “\e790”; content: "\e790";然后将默认的c…

【Delphi】程序实现Windows电脑关机、重启、注销(源代码)

目录 一、API函数说明 1. GetCurrentProcess 2. OpenProcessToken 3. LookupPrivilegeValue 4. AdjustTokenPrivileges 5. ExitWindowsEx 二、Delphi实现源代码 在日常软件开发中&#xff0c;可能会遇到通过程序自动关闭电脑&#xff0c;在早期Windows 9x下&#xff0c;…

西安石油大学C++上机实验汇总

考试题难度就像第三章第五章课后题的难度 基础知识一定要掌握&#xff01;&#xff01;&#xff01; 上机一&#xff1a;类与对象程序设计&#xff08;2 学时&#xff09; 上机目的 掌握声明类的方法。掌握类和类的成员的概念以及定义对象的方法。掌握构造函数和析构函数的…

家居图册制作方法,快来看看

​随着家居设计的流行&#xff0c;越来越多的人开始关注家居装饰和家居用品。据统计&#xff0c;家居市场每年的销售额逐年增长。而家居图册作为家居装饰的重要组成部分&#xff0c;其制作方法也备受关注。 那要怎么制作呢&#xff1f;准备好这个工具&#xff1a;FLBOOK在线制作…

百度Apollo | 实车自动驾驶:感知、决策、执行的无缝融合

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

风口抓猪-借助亚马逊云科技EC2服务器即刻构建PalWorld(幻兽帕鲁)私服~~~持续更新中

Pocketpair出品的生存类游戏《幻兽帕鲁》最近非常火&#xff0c;最高在线人数已逼近200万。官方服务器亚历山大&#xff0c;游戏开发商也提供了搭建私人专用服务器的方案&#xff0c;既可以保证稳定的游戏体验&#xff0c;也可以和朋友一起联机游戏&#xff0c;而且还能自定义经…

大创项目推荐 题目:基于LSTM的预测算法 - 股票预测 天气预测 房价预测

文章目录 0 简介1 基于 Keras 用 LSTM 网络做时间序列预测2 长短记忆网络3 LSTM 网络结构和原理3.1 LSTM核心思想3.2 遗忘门3.3 输入门3.4 输出门 4 基于LSTM的天气预测4.1 数据集4.2 预测示例 5 基于LSTM的股票价格预测5.1 数据集5.2 实现代码 6 lstm 预测航空旅客数目数据集预…

1.25 C++ day2

思维导图 自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() 代码&a…

vue实现甘特图

目录 实现效果 一、安装依赖 二、使用 二、绕过license 实现效果 一、安装依赖 npm i --save vue-gantt-schedule-timeline-calendar 实现甘特图需先安装上述依赖&#xff0c;安装依赖实际上是通过gantt-schedule-timeline-calendar来实现的。所以node_module中因包含以下…

SpringBlade微服务开发平台

采用前后端分离的模式&#xff0c;前端开源两个框架&#xff1a;Sword (基于 React、Ant Design)、Saber (基于 Vue、Element-UI)后端采用SpringCloud全家桶&#xff0c;并同时对其基础组件做了高度的封装&#xff0c;单独开源出一个框架&#xff1a;BladeToolBladeTool已推送至…

视频占内存太大如何压缩?3种简单有效的方法~

很多时候我们需要压缩视频大小&#xff0c;比如节省存储空间、满足平台上传要求等&#xff0c;下面就给大家总结了几个简单且好用的视频压缩技巧&#xff0c;需要的朋友快来学起来~ 方法一&#xff1a;嗨格式压缩大师 嗨格式压缩大师是一款专业的压缩软件&#xff0c;可以压缩…

2024年新提出的算法:一种新的基于数学的优化算法——牛顿-拉夫森优化算法|Newton-Raphson-based optimizer,NRBO

1、简介 开发了一种新的元启发式算法——Newton-Raphson-Based优化器&#xff08;NRBO&#xff09;。NRBO受到Newton-Raphson方法的启发&#xff0c;它使用两个规则&#xff1a;Newton-Raphson搜索规则&#xff08;NRSR&#xff09;和Trap Avoidance算子&#xff08;TAO&#…

【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static

目录 1 ArrayList 集合装箱&#xff0c;拆箱及包装类 2 API 概述和使用Scanner类匿名对象Random生成随机数 3 字符串字符串的31种构造方法字符串的常量池equals和 字符串的获取相关方法字符串的截取方法字符串的转换相关方法字符串的分割方法 4 静态static关键字静态static的内…

【python】爬取豆瓣影评保存到Excel文件中【附源码】

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 【往期相关文章】 爬取豆瓣电影排行榜Top250存储到Excel文件中 爬取豆瓣电影排行榜TOP250存储到CSV文件中 爬取知乎热榜Top50保存到Excel文件中 爬取百度热搜排行榜Top50可视化 爬取斗鱼直播照片保存到本地目录 爬…

qwt的极坐标画雷达方向图

qwt的极坐标画天线方向图 请先看这位博主的专业文章&#xff0c;上面有权威讲解 方向图 曲线方程&#xff1a;matlab&#xff0c;引用博主的公式 f3e10;lamda(3e8)/f;beta2.*pi/lamda; n2; t0:0.01:2*pi;dlamda/4; Wbeta.*d.*cos(t);z1((n/2).*W)-n/2*beta*d;z2((1/2).*W)-1/2…

node.js漏洞总结

js开发的web应用和php/Java最大的区别就是js可以通过查看源代码的方式查看到编写的代码&#xff0c;但是php/Java的不能看到&#xff0c;也就是说js开发的web网页相当于可以进行白盒测试。 流行的js框架有&#xff1a; 1. AngularJS 2. React JS 3. Vue 4. jQuery 5. Backbone…

ChatGPT 和文心一言 | 两大AI助手哪个更胜一筹

欢迎来到英杰社区&#xff1a; https://bbs.csdn.net/topics/617804998 欢迎来到阿Q社区&#xff1a; https://bbs.csdn.net/topics/617897397 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff…

C++ qt标题栏组件绘制

本博文源于笔者在学习C qt制作的标题栏组件&#xff0c;主要包含了&#xff0c;最小化&#xff0c;最大化&#xff0c;关闭。读者在看到这篇博文的时候&#xff0c;可以直接查看如何使用的&#xff0c;会使用了&#xff0c;然后进行复制粘贴源码部分即可。 问题来源 想要制作…

JS-M端事件

移动端也有自己独特的地方。比如触屏事件touch&#xff08;也称触摸事件&#xff09;&#xff0c;Android和IOS都有。 1&#xff09;touch对象代表一个触摸点。触摸点可能是一根手指&#xff0c;也可能是一根触摸笔。触屏事件可响应用户手指&#xff08;或触控笔&#xff09;对…