• 【跟学C++】C++链表——List类(Study11)



     ============================ 【说明】 ===================================================
      大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
      主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
     =======================================================================================
       写在前面
      至此,我们了解了C++的基本语法,但是进一步学习C++,数据结构是必不可少的内容。 数据结构与算法决定了代码测存储方式,以及代码执行效率。
      数据结构的重要性不言而喻, 关于数据结构的基本知识可以转至本人另一专栏====>数据结构】。同样也可以阅读博主【 AI菌】写的【 数据结构与算法】,比较通俗易懂,可以学习学习!

    1、何为List类?

      list是顺序容器,也可以理解为顺序表。它是允许在表中任意位置进行插入与删除操作的数据结构。
      list顺序容器是双向链表,双向链表可以将所存储的元素存放在不同、不相关的位置。每个元素与前后元素链接,并且保持顺序性。
      与单链表(forward_list)相似,只不过单链表只能向前遍历,因此单链表更小更高效。
      与其他顺序容器(array、vector、queue)相比较,list在插入、删除和移动容器中已经获得迭代器的任何位置的元素时,表现更好。
      listforward_list相比其他顺序容器。主要缺点在于:无法通过索引直接得到元素。

    2、List类——成员函数总结

    2.1 构造函数

      通过list类内部的多种重载构造函数,初始化list:

    #include 
    #include 
    using namespace std; 
    
    int main ()
    {
      // 1.通过几种不同的(重载)构造函数初始化链表 
      list<int> first;                                // 整型空链表
      list<int> second (4,100);                       // 四个值为100的链表
      list<int> third (second.begin(),second.end());  // 链表3:值为链表2的内容
      list<int> fourth (third);                       // 赋值链表3的链表4
    
      // 2.迭代器可由数组创建,初始化链表 
      int array[] = {16,2,77,29};
      list<int> fifth (array, array + sizeof(array) / sizeof(int) );
    
      cout << "链表5的内容为: ";
      for (list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
        cout << *it << ' ';
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    结果:

    链表5的内容为: 16 2 77 29
    
    • 1

    2.2 重载运算符

      使用重载运算符=,可以在原有的链表容器中分配新的内容,替换当前内容,同时修改链表容器大小:

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> first (3);      // 链表first 内容为0 0 0
      list<int> second (5);     // 链表second 内容为0 0 0 0 0
    
      second = first;
      first = list<int>();
    
      std::cout << "Size of first: " << int (first.size()) <<endl;
      std::cout << "Size of second: " << int (second.size()) <<endl;
      return 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:

    Size of first: 0
    Size of second: 3
    
    • 1
    • 2

    2.3 迭代器(iterater)

       => begin & end <=

    (1) begin

      begin()返回list容器第一个元素。

    (2) end

      end()返回list容器最后一个元素。

      例:

    #include 
    #include 
    using namespace std;
    
    int main()
    {
      int array[] = {75,23,65,42,13};
      list<int> mylist(array, array+5);
    
      cout << "mylist contains:";
      for (list<int>::iterator it=mylist.begin(); it != mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:

    mylist contains: 75 23 65 42 13
    
    • 1

    注:list::front该成员函数返回的是,指向它的双向迭代器

      

       => rbegin & rend <=

    (3) rbegin

      rbegin()r即代表reverse,颠倒,反向迭代器。rbegin则返回最后一个元素。

    (4) rend

      rend()r即代表reverse,颠倒,反向迭代器。rbegin则返回第一个元素。

      例:

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist;
      for (int i=1; i<=5; ++i) 
      	mylist.push_back(i);
    
      cout << "mylist backwards:";
      for (list<int>::reverse_iterator rit=mylist.rbegin(); rit!=mylist.rend(); ++rit)
        cout << ' ' << *rit;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:

    mylist backwards: 5 4 3 2 1
    
    • 1

    2.4 容量

       => empty <=

    (1) empty
       empty() 判断list容器是否为空。

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist;
      int sum (0);
    
      for(int i=1;i<=10;++i) 
      	mylist.push_back(i);
    
      while (!mylist.empty())
      {
         sum += mylist.front();
         mylist.pop_front();
      }
    
      std::cout << "total: " << sum ;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    结果:

    total: 55
    
    • 1

      

       => size & max_size <=

    (2) size
       size() 返回list容器中元素个数。

    (3) max_size
       size() 返回list容器中最大的元素。
      例:

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist;
     
      for (int i=0; i<10; i++) 
      	mylist.push_back(i);
      cout << "size: " << mylist.size() << endl;
      cout << "max_size: " << mylist.max_size() << endl;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    结果:

    size: 10
    max_size: 357913941
    
    • 1
    • 2

    2.5 访问元素

       => front& back <=

    (1) front
       front() 返回list容器中第一个元素。

    (2) back
       back() 返回list容器中最后一个元素。

      例:

    #include 
    #include 
    using namespace std;
    
    int main()
    {
    	list<int> mylist;
    	for(int i=1; i<=5; ++i) 
    	mylist.push_back(i);
    	
    	cout<<"第一个元素是:"<<mylist.front()<<endl;
    	cout<<"最后一个元素是:"<<mylist.back()<<endl;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:

    第一个元素是:1
    最后一个元素是:5
    
    • 1
    • 2

    2.6 修改链表

       => push_front & push_back <=

    (1) push_front
       push_front() 在初始list容器第一个元素前增加一个数。

    (2) push_back
       push_back() 在初始list容器最后一个元素前增加一个数。

      例:

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist(2,100);    // two ints with a value of 100
      cout << "原始的list中各元素:";
      for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        cout << ' ' << *it;
      cout<<endl;
      
      mylist.push_front(200);
      mylist.push_front(300);
    
      cout << "在list前插入元素后:";
      for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        cout << ' ' << *it;
      cout <<endl;
      
      mylist.push_back(600);
      cout << "在list后插入元素后:";
      for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    结果:

    原始的list中各元素: 100 100
    在list前插入元素后: 300 200 100 100
    在list后插入元素后: 300 200 100 100 600
    
    • 1
    • 2
    • 3

      

       => pop_front & pop_back <=

    (3) pop_front
       pop_front() 删除list容器中第一个元素,同时size减1。

    (4) pop_back
       pop_back() 删除list容器中最后一个元素,同时size减1。

      例:

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist;
      for(int i=1;i<=5;i++)
      	mylist.push_back(i); 
      cout<<"原list中的元素:";
      for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
      	cout<<*it<<" ";
      cout<<endl;
      
      mylist.pop_front();
      cout << "删除list开头第一个元素后:";
      for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
      	cout<<*it<<" ";
      cout<<endl;
      cout<<"list中元素个数:"<<mylist.size()<<endl;
      
      mylist.pop_back();
      cout<<"删除list最后一个元素:";
      for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
      	cout<<*it<<" ";
      cout<<endl;
      cout<<"list中元素个数:"<<mylist.size()<<endl;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    结果:

    原list中的元素:1 2 3 4 5
    删除list开头第一个元素后:2 3 4 5
    list中元素个数:4
    删除list最后一个元素:2 3 4
    list中元素个数:3
    
    • 1
    • 2
    • 3
    • 4
    • 5

      

       => insert <=

    (5) insert
       insert() 在指定的位置前插入新元素。

    #include 
    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist;
      list<int>::iterator it;  //声明it为迭代器 
    
      for(int i=1; i<=5; ++i) mylist.push_back(i); // 1 2 3 4 5
    
      it = mylist.begin();
      ++it;       // it points now to number 2           ^
      mylist.insert (it,10);                        // 1 10 2 3 4 5
    
      // "it" still points to number 2                      ^
      mylist.insert (it,2,20);                      // 1 10 20 20 2 3 4 5
    
      --it;   // it points now to the second 20            ^
    
      std::vector<int> myvector (2,30);
      mylist.insert (it,myvector.begin(),myvector.end());   // 1 10 20 30 30 20 2 3 4 5
                                                        
      std::cout << "mylist contains:";
      for (it=mylist.begin(); it!=mylist.end(); ++it)
        cout << ' ' << *it;
      return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    结果:

    mylist contains: 1 10 20 30 30 20 2 3 4 5
    
    • 1

      

       => erase <=

    (6) erase
      erase() 移除list容器中某个元素某个范围内的元素。

    #include 
    #include 
    using namespace std;
    
    int main ()
    {
      list<int> mylist;
      list<int>::iterator it1,it2;
      // set some values:
      for (int i=1; i<10; ++i) mylist.push_back(i*10);
                                  // 10 20 30 40 50 60 70 80 90
      it1 = it2 = mylist.begin(); // ^^
      advance (it2,6);            // ^                 ^
      ++it1;                      //    ^              ^
      it1 = mylist.erase(it1);   // 10 30 40 50 60 70 80 90
                                  //    ^           ^
    
      it2 = mylist.erase(it2);   // 10 30 40 50 60 80 90
                                  //    ^           ^
    
      ++it1;                      //       ^        ^
      --it2;                      //       ^     ^
    
      mylist.erase (it1,it2);     // 10 30 60 80 90
                                  //        ^
      cout << "mylist contains:";
      for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
        cout << ' ' << *it1;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    结果:

    mylist contains: 10 30 60 80 90
    
    • 1

      

       => swap <=

    (7) swap
      list1.swap(list2) list1容器与list2容器整体互换。

    #include 
    #include 
    
    int main ()
    {
      std::list<int> first (3,100);   // three ints with a value of 100
      std::list<int> second (5,200);  // five ints with a value of 200
    
      first.swap(second);
    
      std::cout << "first contains:";
      for (std::list<int>::iterator it=first.begin(); it!=first.end(); it++)
        std::cout << ' ' << *it;
      std::cout << '\n';
    
      std::cout << "second contains:";
      for (std::list<int>::iterator it=second.begin(); it!=second.end(); it++)
        std::cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    结果:

    first contains: 200 200 200 200 200
    second contains: 100 100 100
    
    • 1
    • 2

      

       => resize <=

    (8) resize
      resize() 调整list容器的大小,使容器包含n个元素。
      若n<当前容器大小,则容器内的元素个数减少至n个元素,其他元素删除(销毁);
      若n>当前容器大小,则容器在尾部补上所需元素,使容器元素个数达到n个,默认补0,若指定元素值,则list.resize(n,value)value为指定元素值。

    #include 
    #include 
    
    int main ()
    {
      std::list<int> mylist;
      // set some initial content:
      for (int i=1; i<10; ++i) mylist.push_back(i); //1 2 3 4 5 6 7 8 9
    
      mylist.resize(5);  //1 2 3 4 5 
      mylist.resize(8,100);  //1 2 3 4 5 100 100 100
      mylist.resize(12);  //1 2 3 4 5 100 100 100 0 0 0 0
    
      std::cout << "mylist contains:";
      for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果:

    mylist contains: 1 2 3 4 5 100 100 100 0 0 0 0
    
    • 1

      

       => clear <=

    (9) clear
      clear() 删除list容器所有元素,使容器size为0。

    #include 
    #include 
    
    int main ()
    {
      std::list<int> mylist;
      std::list<int>::iterator it;
    
      mylist.push_back (100);
      mylist.push_back (200);
      mylist.push_back (300);
    
      std::cout << "mylist contains:";
      for (it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      std::cout << '\n';
    
      mylist.clear(); //清空所有元素 
      mylist.push_back (1101);
      mylist.push_back (2202);
    
      std::cout << "mylist contains:";
      for (it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    结果:

    mylist contains: 100 200 300
    mylist contains: 1101 2202
    
    • 1
    • 2

    2.7 其他

       => remove & remove_if <=

    (1) remove
      remove(value) 删除list容器中所有与value相同的元素,并减小size值。
      remove()与上面所述的erase()不一样,erase作为迭代器删除元素,而remove()则是依据元素值删除元素。

    #include 
    #include 
    
    int main ()
    {
      int myints[]= {5,6,8,8,9,45,8};
      std::list<int> mylist (myints,myints+7);
    
      mylist.remove(8); //删除链表中所有为8的元素 
    
      std::cout << "mylist contains:";
      for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    结果:

    mylist contains: 5 6 9 45
    
    • 1

    (2) remove_if
      remove_if(condition)依据condition条件删除容器中部分元素。

    #include 
    #include 
    
    // a predicate implemented as a function:
    bool single_digit (const int& value) { return (value<10); }
    
    // a predicate implemented as a class:
    struct is_odd {
      bool operator() (const int& value) { return (value%2)==1; }
    };
    
    int main ()
    {
      int myints[]= {15,36,7,17,20,39,4,1};
      std::list<int> mylist (myints,myints+8);   // 15 36 7 17 20 39 4 1
    
      mylist.remove_if (single_digit);           // 15 36 17 20 39
    
      mylist.remove_if (is_odd());               // 36 20
    
      std::cout << "mylist contains:";
      for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    结果:

    mylist contains: 36 20
    
    • 1

      

       => unique <=

    (3) unique
      list.unique()删除容器中相同的元素,只保留最前面(第一个)元素。
      list.unique(condition)删除容器中不符合condition的元素。

    #include 
    #include 
    #include 
    
    // 判断元素整数部分相同 
    bool same_integral_part (double first, double second)
    { return ( int(first)==int(second) ); }
    
    // 判断相邻元素距离是否小于5 
    struct is_near {
      bool operator() (double first, double second)
      { return (fabs(first-second)<5.0); }
    };
    
    int main ()
    {
      double mydoubles[]={ 12.15,  2.72, 73.0,  12.77,  3.14,
                           12.77, 73.35, 72.25, 15.3,  72.25 };
      std::list<double> mylist (mydoubles,mydoubles+10);
       
      mylist.sort();             //  2.72,  3.14, 12.15, 12.77, 12.77,
                                 // 15.3,  72.25, 72.25, 73.0,  73.35
      //版本1 
      mylist.unique();           //  2.72,  3.14, 12.15, 12.77
                                 // 15.3,  72.25, 73.0,  73.35
      //版本2 
      mylist.unique (same_integral_part);  //  2.72,  3.14, 12.15
                                           // 15.3,  72.25, 73.0
      
      mylist.unique (is_near());           //  2.72, 12.15, 72.25
    
      std::cout << "mylist contains:";
      for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    结果:

    mylist contains: 2.72 12.15 72.25
    
    • 1

      

       => sort <=

    (4) sort
      list.sort()依据ASCII码进行排序。
      list.sort(comp)依据自定义规则comp排序。

    #include 
    #include 
    #include 
    #include 
    
    // comparison, not case sensitive.
    bool compare_nocase (const std::string& first, const std::string& second)
    {
      unsigned int i=0;
      while ( (i<first.length()) && (i<second.length()) )
      {
        if (tolower(first[i])<tolower(second[i])) return true;
        else if (tolower(first[i])>tolower(second[i])) return false;
        ++i;
      }
      return ( first.length() < second.length() );
    }
    
    int main ()
    {
      std::list<std::string> mylist;
      std::list<std::string>::iterator it;
      mylist.push_back ("one");
      mylist.push_back ("two");
      mylist.push_back ("Three");
    
      mylist.sort();
    
      std::cout << "mylist contains:";
      for (it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      std::cout << '\n';
    
      mylist.sort(compare_nocase);
    
      std::cout << "mylist contains:";
      for (it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      std::cout << '\n';
    
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    结果:

    mylist contains: Three one two
    mylist contains: one Three two
    
    • 1
    • 2

      

       => reverse<=

    (5) reverse
      list.reverse()颠倒list容器中的元素,注意区别上面swap()成员函数的用法。

    #include 
    #include 
    
    int main ()
    {
      std::list<int> mylist;
    
      for (int i=1; i<10; ++i) mylist.push_back(i);
    
      mylist.reverse();
    
      std::cout << "mylist contains:";
      for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    结果:

    mylist contains: 9 8 7 6 5 4 3 2 1
    
    • 1

    3、总结

      最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏。

  • 相关阅读:
    postgresql_anonymizer使用
    100106. 元素和最小的山形三元组 I
    TypeScript常见面试题第十一节
    Api 接口优化有哪些技巧?
    MCE | 第二代 HIV-INSTI 的作用方式
    基于低代码平台实现的内外OA协同办公系统
    MacBook当作Win电脑副屏
    归并排序 Merge Sort
    含文档+PPT+源码等]精品基于Nodejs实现的学生宿舍管理系统[包运行成功]Nodejs毕业设计计算机项目源码
    ceph分布式存储
  • 原文地址:https://blog.csdn.net/qq_41225961/article/details/126489626