C/C++编程:STL list的使用

概述

  • list<>由双向链表实现而成。这意味着list内的每个元素都以一部分内存指示其前导元素和后继元素
  • list<>不提供随机访问,因此如果你要访问第10个元素,必须沿着链表依次走过前9个元素
  • list<>的优势是:在任何位置上执行安插或者删除动作都非常快速,因为只需要改变链接就好

构造函数&&析构函数

C/C++编程:STL list的使用_第1张图片

 

非更易型操作

C/C++编程:STL list的使用_第2张图片

赋值操作 

C/C++编程:STL list的使用_第3张图片

 

元素访问

C/C++编程:STL list的使用_第4张图片

 

 C/C++编程:STL list的使用_第5张图片

 

迭代器

C/C++编程:STL list的使用_第6张图片

 C/C++编程:STL list的使用_第7张图片

 

插入&&删除

C/C++编程:STL list的使用_第8张图片

 C/C++编程:STL list的使用_第9张图片

 C/C++编程:STL list的使用_第10张图片

 

 

Splice(接和)函数以及会改变元素次序的函数

C/C++编程:STL list的使用_第11张图片

 C/C++编程:STL list的使用_第12张图片

 

异常处理

C/C++编程:STL list的使用_第13张图片

 

 

 

 

实例

构造

#include 
#include 
#include 

template
std::ostream& operator<<(std::ostream& s, const std::list& v)
{
    s.put('[');
    char comma[3] = {'\0', ' ', '\0'};
    for (const auto& e : v) {
        s << comma << e;
        comma[0] = ',';
    }
    return s << ']';
}

int main()
{
    // C++11 初始化器列表语法:
    std::list words1 {"the", "frogurt", "is", "also", "cured"};
    std::cout << "words1: " << words1 << '\n';

    // words2 == words1
    std::list words2(words1.begin(), words1.end());
    std::cout << "words2: " << words2 << '\n';

    // words3 == words1
    std::list words3(words1);
    std::cout << "words3: " << words3 << '\n';

    // words4 为 {"Mo", "Mo", "Mo", "Mo", "Mo"}
    std::list words4(5, "Mo");
    std::cout << "words4: " << words4 << '\n';
    return 0;
}

C/C++编程:STL list的使用_第14张图片

std::list::operator=、std::list::assign

  • std::list::assign作用:替换容器的内容
  • std::list::operator=作用:替换容器的内容
#include 
#include 
#include 

void display_sizes(const std::list& nums1,
                   const std::list& nums2,
                   const std::list& nums3)
{
    std::cout << "nums1: " << nums1.size()
              << " nums2: " << nums2.size()
              << " nums3: " << nums3.size() << '\n';
}

int main()
{
    std::list nums1 {3, 1, 4, 6, 5, 9};
    std::list nums2;
    std::list nums3;

    std::cout << "Initially:\n";
    display_sizes(nums1, nums2, nums3);

    // 复制赋值从 nums1 复制数据到 nums2
    nums2 = nums1;

    std::cout << "After assigment:\n";
    display_sizes(nums1, nums2, nums3);

    // 移动赋值从 nums1 移动数据到 nums3,
    // 一同修改 nums1 和 nums3
    nums3 = std::move(nums1);

    std::cout << "After move assigment:\n";
    display_sizes(nums1, nums2, nums3);



    return 0;
}

C/C++编程:STL list的使用_第15张图片

#include 
#include 
#include 



int main()
{
    std::list characters;

    characters.assign(5, 'a');

    for (char c : characters) {
        std::cout << c << ' ';
    }

    characters.assign({'\n', 'C', '+', '+', '1', '1', '\n'});

    for (char c : characters) {
        std::cout << c;
    }

    return 0;
}

front、back

  • std::list::front:返回到容器首元素的引用。在空容器上调用 front 会引发未定义行为

  • std::list::back:返回到容器中最后一个元素的引用。在空容器上调用 back 会引发未定义行为

#include 
#include 

int main()
{
    std::list letters {'o', 'm', 'g', 'w', 't', 'f'};

    if (!letters.empty()) {
        std::cout << "The first character is: " << letters.front() << '\n';
        std::cout << "The last character is: " << letters.back() << '\n';
    }
}

begin、end、rbegin、rend

  • begin:返回指向list首元素的迭代器
  • end:   返回指向 list 末元素后一元素的迭代器。
#include 
#include 
#include 
#include 

int main()
{
    std::list nums {1, 2, 4, 8, 16};
    std::list fruits {"orange", "apple", "raspberry"};
    std::list empty;

    // 求和 list nums 中的所有整数(若存在),仅打印结果。
    std::cout << "Sum of nums: " <<
        std::accumulate(nums.begin(), nums.end(), 0)  << "\n";

    // 打印 list fruits 中的首个 fruis
    if(!fruits.empty()){
        std::cout << "First fruit: " << *fruits.begin() << "\n";
    }

    if (empty.begin() == empty.end())
        std::cout << "list 'empty' is indeed empty.\n";
}

C/C++编程:STL list的使用_第16张图片

empty、size、max_size、resize

  • empty:检查容器是否为空
  • size:返回容器中的元素数,相当于 std::distance(begin(), end())
  • max_size:返回最大可以容纳的元素个数

  • resize:重设容器大小以容纳count个元素

#include 
#include 
 
int main()
{
    std::list numbers;
    std::cout << "Initially, numbers.empty(): " << numbers.empty() << '\n';
 
    numbers.push_back(42);
    numbers.push_back(13317); 
    std::cout << "After adding elements, numbers.empty(): " << numbers.empty() << '\n';
}

#include 
#include 
#include 

int main()
{
    std::list numbers;
    std::cout << "max size: " << numbers.max_size() << '\n';
    std::cout << "max size: " << std::numeric_limits>::max().max_size()<< '\n';
}

#include 
#include 
int main()
{
    std::list c = {1, 2, 3};
    std::cout << "The list holds: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
    c.resize(5);
    std::cout << "After resize up to 5: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
    c.resize(2);
    std::cout << "After resize down to 2: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
}

swap

#include 
#include 

template
Os& operator<<(Os& os, const Co& co) {
    os << "{";
    for (auto const& i : co) { os << ' ' << i; }
    return os << " } ";
}

int main()
{
    std::list a1{1, 2, 3}, a2{4, 5};

    auto it1 = std::next(a1.begin());
    auto it2 = std::next(a2.begin());

    int & ref1 = a1.front();
    int & ref2 = a2.front();
    
    std::cout << a1 << a2 << *it1 << ' ' << *it2 << ' ' << ref1 << ' ' << ref2 << '\n';
    a1.swap(a2);
    std::cout << a1 << a2 << *it1 << ' ' << *it2 << ' ' << ref1 << ' ' << ref2 << '\n';

    // 注意交换后迭代器与引用保持与其原来的元素关联,例如指向 'a1' 中值为 2 的元素的 it1 仍指向同一元素,
    // 尽管此元素被移动到 'a2' 中。
}

效果

#include 
#include 
#include 
 
int main()
{
    std::list alice{1, 2, 3};
    std::list bob{7, 8, 9, 10};
 
    auto print = [](const int& n) { std::cout << " " << n; };
 
    // 打印交换前的状态
    std::cout << "alice:";
    std::for_each(alice.begin(), alice.end(), print);
    std::cout << '\n';
    std::cout << "bob  :";
    std::for_each(bob.begin(), bob.end(), print);
    std::cout << '\n';
 
    std::cout << "-- SWAP\n";
    std::swap(alice,bob);
 
    // 打印交换后的状态
    std::cout << "alice:";
    std::for_each(alice.begin(), alice.end(), print);
    std::cout << '\n';
    std::cout << "bob  :";
    std::for_each(bob.begin(), bob.end(), print);
    std::cout << '\n';
}

效果

clear、erase

  • clear:从容器擦除所有元素。此调用后 size() 返回零。
  • erase:从容器擦除指定的元素

  • 1) 移除位于 pos 的元素。
  • 2) 移除范围 [first; last) 中的元素。
#include 
#include 
#include 

int main()
{
    std::list container{1, 2, 3};

    auto print = [](const int& n) { std::cout << " " << n; };

    std::cout << "Before clear:";
    std::for_each(container.begin(), container.end(), print);
    std::cout << "\nSize=" << container.size() << '\n';

    std::cout << "Clear\n";
    container.clear();

    std::cout << "After clear:";
    std::for_each(container.begin(), container.end(), print);
    std::cout << "\nSize=" << container.size() << '\n';
}

C/C++编程:STL list的使用_第17张图片

#include 
#include 
#include 
 
int main( )
{
    std::list c{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (auto &i : c) {
        std::cout << i << " ";
    }
    std::cout << '\n';
 
    c.erase(c.begin());
 
    for (auto &i : c) {
        std::cout << i << " ";
    }
    std::cout << '\n';
 
    std::list::iterator range_begin = c.begin();
    std::list::iterator range_end = c.begin();
    std::advance(range_begin,2);
    std::advance(range_end,5);
 
    c.erase(range_begin, range_end);
 
    for (auto &i : c) {
        std::cout << i << " ";
    }
    std::cout << '\n';
}

#include 
#include 
#include 
 
void print_container(const std::list& c)
{
    for (auto x : c) {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}
 
int main()
{
    std::list cnt(10);
    std::iota(cnt.begin(), cnt.end(), '0');
 
    std::cout << "Init:\n";
    print_container(cnt);
 
    auto erased = std::erase(cnt, '3');
    std::cout << "Erase \'3\':\n";
    print_container(cnt);
 
    std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
    std::cout << "Erase all even numbers:\n";
    print_container(cnt);
    std::cout << "In all " << erased << " even numbers were erased.\n";
}

C/C++编程:STL list的使用_第18张图片

emplace、emplace_front、push_back

  • emplace:直接于pos前插入元素到容器中
  • emplace_front、push_front:插入新元素到容器起始
  • emplace_back、push_back:插入新元素到容器末尾

  • pop_back:移除容器的末元素。在空容器上调用 pop_back 导致未定义行为。指向被擦除元素的迭代器和引用被非法化。
#include 
#include 
#include 

struct A{
    std::string s;
    A(std::string str) : s(std::move(str))  { std::cout << " constructed\n"; }
    A(const A& o) : s(o.s) { std::cout << " copy constructed\n"; }
    A(A&& o) : s(std::move(o.s)) { std::cout << " move constructed\n"; }
    A& operator=(const A& other) {
        s = other.s;
        std::cout << " copy assigned\n";
        return *this;
    }
    A& operator=(A&& other) {
        s = std::move(other.s);
        std::cout << " move assigned\n";
        return *this;
    }
};

int main()
{
    std::list container;

    std::cout << "construct 2 times A:\n";
    A two { "two" };
    A three { "three" };

    std::cout << "emplace:\n";
    container.emplace(container.end(), "one");

    std::cout << "emplace with A&:\n";
    container.emplace(container.end(), two);

    std::cout << "emplace with A&&:\n";
    container.emplace(container.end(), std::move(three));

    std::cout << "content:\n";
    for (const auto& obj : container)
        std::cout << ' ' << obj.s;
    std::cout << '\n';
}

C/C++编程:STL list的使用_第19张图片

#include 
#include 
 
template
void print(T const & xs)
{
    std::cout << "[ ";
    for(auto && x : xs) {
        std::cout << x << ' ';
    }
    std::cout << "]\n";
}
 
int main()
{
    std::list numbers;
 
    print(numbers); 
 
    numbers.push_back(5);
    numbers.push_back(3);
    numbers.push_back(4);
 
    print(numbers); 
 
    numbers.pop_back();
 
    print(numbers); 
}

merge

  • merge:归并两排序链表为一个

#include 
#include 
 
std::ostream& operator<<(std::ostream& ostr, const std::list& list)
{
    for (auto &i : list) {
        ostr << " " << i;
    }
    return ostr;
}
 
int main()
{
    std::list list1 = { 5,9,0,1,3 };
    std::list list2 = { 8,7,2,6,4 };
 
    list1.sort();
    list2.sort();
    std::cout << "list1:  " << list1 << "\n";
    std::cout << "list2:  " << list2 << "\n";
    list1.merge(list2);
    std::cout << "merged: " << list1 << "\n";
}

splice

  • splice:从一个list转移元素给另一个。不复制或者移动元素,仅重指向链表节点的内部指针

#include 
#include 

std::ostream& operator<<(std::ostream& ostr, const std::list& list)
{
    for (auto &i : list) {
        ostr << " " << i;
    }
    return ostr;
}

int main()
{
    std::list list1 = { 1, 2, 3, 4, 5 };
    std::list list2 = { 10, 20, 30, 40, 50 };

    auto it = list1.begin();
    std::advance(it, 2);

    list1.splice(it, list2);

    std::cout << "list1: " << list1 << "\n";
    std::cout << "list2: " << list2 << "\n";

    list2.splice(list2.begin(), list1, it, list1.end());

    std::cout << "list1: " << list1 << "\n";
    std::cout << "list2: " << list2 << "\n";
}

C/C++编程:STL list的使用_第20张图片

remove, remove_if

#include 
#include 
 
int main()
{
    std::list l = { 1,100,2,3,10,1,11,-1,12 };
 
    l.remove(1); // 移除两个等于 1 的元素
    l.remove_if([](int n){ return n > 10; }); // 移除全部大于 10 的元素
 
    for (int n : l) {
        std::cout << n << ' '; 
    }
    std::cout << '\n';
}

reverse

  • 作用:逆转容器中的元素顺序。不非法化任何引用或迭代器。
#include 
#include 
 
std::ostream& operator<<(std::ostream& ostr, const std::list& list)
{
    for (auto &i : list) {
        ostr << " " << i;
    }
    return ostr;
}
 
int main()
{
    std::list list = { 8,7,5,9,0,1,3,2,6,4 };
 
    std::cout << "before:     " << list << "\n";
    list.sort();
    std::cout << "ascending:  " << list << "\n";
    list.reverse();
    std::cout << "descending: " << list << "\n";
}

unique

  • 从容器移除所有相继的重复元素。只留下相等元素组中的第一个元素。
#include 
#include 
 
int main()
{
  std::list x = {1, 2, 2, 3, 3, 2, 1, 1, 2};
 
  std::cout << "contents before:";
  for (auto val : x)
    std::cout << ' ' << val;
  std::cout << '\n';
 
  x.unique();
  std::cout << "contents after unique():";
  for (auto val : x)
    std::cout << ' ' << val;
  std::cout << '\n';
 
  return 0;
}

比较

#include 
#include 
 
int main()
{
    std::list alice{1, 2, 3};
    std::list bob{7, 8, 9, 10};
    std::list eve{1, 2, 3};
 
    std::cout << std::boolalpha;
 
    // 比较不相等的容器
    std::cout << "alice == bob returns " << (alice == bob) << '\n';
    std::cout << "alice != bob returns " << (alice != bob) << '\n';
    std::cout << "alice <  bob returns " << (alice < bob) << '\n';
    std::cout << "alice <= bob returns " << (alice <= bob) << '\n';
    std::cout << "alice >  bob returns " << (alice > bob) << '\n';
    std::cout << "alice >= bob returns " << (alice >= bob) << '\n';
 
    std::cout << '\n';
 
    // 比较相等的容器
    std::cout << "alice == eve returns " << (alice == eve) << '\n';
    std::cout << "alice != eve returns " << (alice != eve) << '\n';
    std::cout << "alice <  eve returns " << (alice < eve) << '\n';
    std::cout << "alice <= eve returns " << (alice <= eve) << '\n';
    std::cout << "alice >  eve returns " << (alice > eve) << '\n';
    std::cout << "alice >= eve returns " << (alice >= eve) << '\n';
}

C/C++编程:STL list的使用_第21张图片

如果想要扩展list的功能

看个例子:

#include 
#include 



template
class List : public std::list {
public:
    template
    List(ARGS &&...args) : std::list(std::forward(args)...) {};

    ~List() = default;

    void append(List &other) {
        if (other.empty()) {
            return;
        }
        this->insert(this->end(), other.begin(), other.end());
        other.clear();
    }

    template
    void for_each(FUNC &&func) {
        for (auto &t : *this) {
            func(t);
        }
    }

    template
    void for_each(FUNC &&func) const {
        for (auto &t : *this) {
            func(t);
        }
    }
};

你可能感兴趣的:(C++,c++,c语言,链表)