zoukankan      html  css  js  c++  java
  • List容器

    1、List

    (1)定义

    List是一种序列式容器。List容器完成的功能实际上和数据结构中的双向链表是极其相似的,List中的数据元素是通过链表指针串连成逻辑意义上的线性表,也就是List也具有链表的主要优点,即:在链表的任一位置进行元素的插入、删除操作都是快速的。

    (2)底层实现

    List的实现大概是这样的,类似双向链表,:list的每个节点有三个域:前驱元素指针域、数据域和后继元素指针域。

    前驱元素指针域保存了前驱元素的首地址;数据域则是本节点的数据;后继元素指针域则保存了后继元素的首地址。其实,List和循环链表也有相似的地方,即:头节点的前驱元素指针域保存的是链表中尾元素的首地址,List的尾节点的后继元素指针域则保存了头节点的首地址,这样,List实际上就构成了一个双向循环链。

    由于List元素节点并不要求在一段连续的内存中,显然在List中是不支持快速随机存取的,因此对于迭代器,只能通过“++”或“--”操作将迭代器移动到后继/前驱节点元素处。而不能对迭代器进行+n或-n的操作,这点是与vector等不同的地方。

    (3)使用

    使用list容器之前必须加上<list>头文件:#include<list>;

    List属于std命名域的内容,因此需要通过命名限定:using std::list;也可以直接使用全局的命名空间方式:using namespace std。

    (4)特点

    优点:(1)内存不连续

              (2)动态操作,插入与删除效率高;

              (3)可在两端进行pop,push。

    缺点:(1)不能随机访问;

              (2)相对于vector占用内存多(需要存储前驱后继元素指针域)。

    2、成员函数

    (1)构造函数

    /*构造函数*/
    list() 
    //声明一个空列表;
    list(n) 
    //声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的
    list(n,val) 
    //声明一个由n个元素的列表,每个元素都是由其复制构造函数T(val)得来的
    list(n,val) 
    //声明一个和上面一样的列表
    list(first,last) 
    //声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素

    (2)赋值操作

    assign():
    //具体和vector中的操作类似,也是有两种情况:
    //第一种是:l1.assign(n,val)将 l1中元素变为n个T(val);
    //第二种情况是:l1.assign(l2.begin(),l2.end())将l2中的从l2.begin()到l2.end()之间的数值赋值给l1
    
    c.assign(n,num);
    //将n个num拷贝赋值给链表c。
    c.assign(beg,end);
    //将[beg,end)区间的元素拷贝赋值给链表c。

    示例:

    int a[5] = {1,2,3,4,5};
        list<int> a1;
        list<int>::iterator it;
        a1.assign(2,10);
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        a1.assign(a,a+5);
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;

    (3)插入操作

    push_back();
    //push_back()从list的末端插入
    push_front():
    //push_front()实现的从list的头部插入
    
    insert():
    //在指定位置插入一个或多个元素(三个重载)
    c.insert(pos,num);
    //在pos位置插入元素num。
    c.insert(pos,n,num);
    //在pos位置插入n个元素num。
    c.insert(pos,beg,end);
    //在pos位置插入区间为[beg,end)的元素。

    示例:

    list<int> a1{1,2,3,4,5};
        list<int>::iterator it;
        cout << "insert before:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.insert(a1.begin(),0);
        cout << "insert(pos,num) after:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.insert(a1.begin(),2,88);
        cout << "insert(pos,n,num) after:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
        int arr[5] = {11,22,33,44,55};
        a1.insert(a1.begin(),arr,arr+3);
        cout << "insert(pos,beg,end) after:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
    list<int> a1{1,2,3,4,5};
        a1.push_back(10);
        list<int>::iterator it;
        cout << "push_back:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.pop_back();
        cout << "pop_back:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.push_front(20);
        cout << "push_front:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.pop_front();
        cout << "pop_front:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;

    (4)删除操作

    pop_back();
    //通过pop_front()删除第一个元素
    pop_front():
    //删除最后一个元素
    //序列必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。
    
    clear(): 
    //清空list中的所有元素。
    
    erase():
    //删除一个元素或一个区域的元素(两个重载)
    l1.erase(l1.begin()); 
    //将l1的第一个元素删除。
    l1.erase(l1.begin(),l1.end()); 
    //将l1的从begin()到end()之间的元素删除。
    
    remove(num);
    //删除链表中匹配num的元素
    remove_if(comp);
    //删除条件满足的元素,参数为自定义的回调函数
    unique();
    //删除相邻的元素

    示例:

    list<int> a1{1,2,3,4,5};
        list<int>::iterator it;
        cout << "clear before:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << "	";
        }
        cout << endl;
        a1.clear();
        cout << "clear after:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << "	";
        }
        cout << endl;
    
    list<int> a1{1,2,3,4,5};
        list<int>::iterator it;
        cout << "erase before:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        a1.erase(a1.begin());
        cout << "erase after:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
    list<int> a1{1,2,3,4,5};
        a1.remove(3);
        list<int>::iterator it;
        cout << "remove():";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
    list<int> a1{1,2,3,4,5};
        a1.remove_if([](int n){return n<3;});
        list<int>::iterator it;
        cout << "remove_if():";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
    list<int> a1{1,1,3,3,5};
        a1.unique();
        list<int>::iterator it;
        cout << "unique:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        return 0;

    (5)定位操作

    begin();
    //通过调用list容器的成员函数begin()得到一个指向容器起始位置的iterator
    end():,
    //调用list容器的 end()函数来得到list末端下一位置,相当于:int a[n]中的第n+1个位置a[n],
    //实际上是不存在的,不能访问,经常作为循环结束判断结束条件使用。
    
    c.rbegin();
    //返回逆向链表的第一个元素,即c链表的最后一个数据。
    c.rend();
    //返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。
    
    front();
    //通过front()可以获得list容器中的头部元素
    back(): ,
    //通过back()可以获得list容器的最后一个元素
    //但是有一点要注意,就是list中元素是空的时候,这时候调用front()和back()会发生什么呢?
    //实际上会发生不能正常读取数据的情况,但是这并不报错,那我们编程序时就要注意了,建议在使用之前最好先调用empty()函数判断list是否为空。
    
    reverse():
    //通过reverse()完成list的逆置。

    示例:

    list<int> a1{1,2,3,4,5};
    list<int>::iterator it;
    for(it = a1.begin();it!=a1.end();it++){
    cout << *it << "	";
    }
    cout << endl;
    
    list<int> a1{1,2,3,4,5};
    list<int>::reverse_iterator it;
    for(it = a1.rbegin();it!=a1.rend();it++){
    cout << *it << "	";
    }
    cout << endl;
    
    list<int> a1{1,2,3,4,5};
    if(!a1.empty()){
    cout << "the first number is:" << a1.front() << endl;
    cout << "the last number is:" << a1.back() << endl;
    }
    
    list<int> a1{1,2,3,4,5};
        a1.reverse();
        list<int>::iterator it;
        cout << "reverse:";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;

    (6)数据大小

    empty():
    //利用empty() 判断list是否为空。
    resize(): 
    //如果调用resize(n)将list的长度改为只容纳n个元素,超出的元素将被删除,
    //如果需要扩展那么调用默认构造函数T()将元素加到list末端。
    //如果调用resize(n,val),则扩展元素要调用构造函数T(val)函数进行元素构造,其余部分相同。
    
    c.size();
    //返回链表c中实际元素的个数。
    c.max_size();
    //链表c可能容纳的最大元素数量。

    示例:

    list<int> a1{1,2,3,4,5};
        a1.resize(8);
        list<int>::iterator it;
        cout << "resize(n):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.resize(10, 10);
        cout << "resize(n,num):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;

    (7)交换操作

    swap():交换两个链表(两个重载),一个是l1.swap(l2); 另外一个是swap(l1,l2),都可能完成连个链表的交换。
    c1.swap(c2);      将c1和c2交换。
    swap(c1,c2);      同上。

    示例:

    list<int> a1{1,2,3,4,5},a2,a3;
        a2.swap(a1);
        list<int>::iterator it;
        cout << "a2.swap(a1):";
        for(it = a2.begin();it!=a2.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        swap(a3,a2);
        cout << "swap(a3,a2):";
        for(it = a3.begin();it!=a3.end();it++){
            cout << *it << " ";
        }
        return 0;

    (8)合并操作

    merge():
    //合并两个链表并使之默认升序(也可改),l1.merge(l2,greater<int>()); 
    //调用结束后l2变为空,l1中元素包含原来l1 和 l2中的元素,并且排好序,升序。
    //其实默认是升序,greater<int>()可以省略,另外greater<int>()是可以变的,也可以不按升序排列。
    c1.merge(c2);
    //合并2个有序的链表并使之有序,从新放到c1里,释放c2。
    c1.merge(c2,comp);
    //合并2个有序的链表并使之按照自定义规则排序之后从新放到c1中,释放c2。
    
    c1.splice(c1.beg,c2);
    // 将c2连接在c1的beg位置,释放c2
    c1.splice(c1.beg,c2,c2.beg);
    //将c2的beg位置的元素连接到c1的beg位置,并且在c2中施放掉beg位置的元素
    c1.splice(c1.beg,c2,c2.beg,c2.end);
    //c2的[beg,end)位置的元素连接到c1的beg位置并且释放c2的[beg,end)位置的元素

    示例:

    list<int> a1{1,2,3},a2{4,5,6};
        a1.merge(a2);
        list<int>::iterator it;
        cout << "a1.merge(a2):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a2.merge(a1,[](int n1,int n2){return n1>n2;});
        cout << "a2.merge(a1,comp):";
        for(it = a2.begin();it!=a2.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
    list<int> a1{1,2,3},a2{4,5,6};
        a1.splice(a1.begin(), a2);
        list<int>::iterator it;
        cout << "a1.merge(a2):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
    
    list<int> a1{1,2,3},a2{4,5,6};
        a1.splice(a1.begin(), a2,++a2.begin());
        list<int>::iterator it;
        cout << "a1.merge(a2):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        return 0;
    
    list<int> a1{1,2,3},a2{4,5,6};
        a1.splice(a1.begin(),a2,a2.begin(),a2.end());
        list<int>::iterator it;
        cout << "a1.merge(a2):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        return 0;

    (9)排序操作

    c.sort()       将链表排序,默认升序
    c.sort(comp)       自定义回调函数实现自定义排序

    示例:

    list<int> a1{1,3,2,5,4};
        a1.sort();
        list<int>::iterator it;
        cout << "sort():";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;
        
        a1.sort([](int n1,int n2){return n1>n2;});
        cout << "sort(function point):";
        for(it = a1.begin();it!=a1.end();it++){
            cout << *it << " ";
        }
        cout << endl;

    (10)重载运算符

    operator==
    operator!=
    operator<
    operator<=
    operator>
    operator>=

    示例:

    list<int> a1 {1,2,3,4,5},a2;
    a2 = a1;
    list<int>::iterator it;
    for(it = a2.begin();it!=a2.end();it++){
        cout << *it << endl;
    }
    

      

  • 相关阅读:
    IDEA快速搭建 SpringCloud 注册中心与
    -bash: nginx: 未找到命令 (command not found) 解决方案
    【转载】02-PowerDesigner的下载及安装
    redis.conf配置文件配置项解析
    Linux 重启防火墙失败
    hduoj 3459 Rubik 2×2×2
    sdutoj 2605 A^X mod P
    hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup
    hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup
    hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup
  • 原文地址:https://www.cnblogs.com/yedushusheng/p/5519959.html
Copyright © 2011-2022 走看看