zoukankan      html  css  js  c++  java
  • 4.lists(双向链表)

    一.概述

      是一个线性链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。由于其结构的原因,list 随机检索的性能非常的不好,因为它不像vector 那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。

      虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list 的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector 会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的。

    二.特点

    (1) 不使用连续的内存空间这样可以随意地进行动态操作;
    (2) 可以在内部任何位置快速地插入或删除,当然也可以在两端进行push和pop 。
    (3) 不能进行内部的随机访问,即不支持[ ] 操作符和vector.at() ; 

    Lists将元素按顺序储存在链表中,与向量(vectors)相比,它允许快速的插入和删除,但是随机访问却比较慢.。

    C++标准规定:每种的容器都必须提供自己的迭代器,容器提供的一些函数以获得迭代器并以之遍历所有元素,而迭代器就是容器提供的一种遍历的方式,其本质上是一个指针。

    三.常用API

    assign() 给list赋值
    back() 返回最后一个元素
    begin() 返回指向第一个元素的迭代器
    clear() 删除所有元素
    empty() 如果list是空的则返回true
    end() 返回末尾的迭代器
    erase() 删除一个元素
    front() 返回第一个元素
    get_allocator() 返回list的配置器
    insert() 插入一个元素到list中
    max_size() 返回list能容纳的最大元素数量
    merge() 合并两个list
    pop_back() 删除最后一个元素
    pop_front() 删除第一个元素
    push_back() 在list的末尾添加一个元素
    push_front() 在list的头部添加一个元素
    rbegin() 返回指向第一个元素的逆向迭代器
    remove() 从list删除元素
    remove_if() 按指定条件删除元素
    rend() 指向list末尾的逆向迭代器
    resize() 改变list的大小
    reverse() 把list的元素倒转
    size() 返回list中的元素个数
    sort() 给list排序
    splice() 合并两个list
    swap() 交换两个list
    unique() 删除list中重复的元素

    四.示例Demo

    1) 使用迭代器遍历当前list元素

    #include <iostream>
    #include <stdlib.h>
    #include <list>
    
    using namespace std;
    #pragma warning(disable:4996)
    
    /*
    const int arraysize = 10;
    int ai[arraysize] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int *begin = ai;
    int *end = ai + arraysize; // end指向的是9后面的空间
    for (int *pi = begin; pi != end; ++pi)
    {
        cout << *pi << "";
    }
    */
    
    
    // 使用迭代器遍历当前链表1
    void printlist(list<int> &l)
    {
        for (list<int>::iterator p = l.begin(); p != l.end(); ++p)
        {
            cout << "current item is: " << *p << endl;
        }
    }
    
    // 使用迭代器遍历当前链表2
    void printlist2(list<int> &l)
    {
        list<int>::iterator current = l.begin();                      // 返回第一个元素的迭代器,头指针,迭代器本质上就是一个指针
        while (current != l.end())                                    // l.end() 代表末尾迭代器 尾指针
        {
            cout <<"current item is: " <<*current << endl;
            current++;
        }
    
    }
    
    
    int main() {
        
    
        list<int> l;
    
        for (int i = 0; i < 5; i++)
        {
            l.push_back(i + 1);
        }
    
        cout << "current list size is: " << l.size() << endl;
        printlist(l);
    
        printf("----------------------------------------
    ");
    
        list<int> s;
        for (int i = 0; i < 10; i++)
        {
            s.push_front(0);
        }
    
        list<int>::iterator s_iterator = s.begin();                     // 从链表中取出链表的开头,赋值给迭代器,初始位置为0
        s_iterator++;
        s_iterator++;
        s_iterator++;                                                   // 当前迭代器运行到3号位置(从0开始)
        s.insert(s_iterator, 5);                                        // 在3号位置插入
    
        printlist2(s);
    
        system("pause");
        return 0;
    }

    运行结果:

    current list size is: 5
    current item is: 1
    current item is: 2
    current item is: 3
    current item is: 4
    current item is: 5
    ----------------------------------------
    current item is: 0
    current item is: 0
    current item is: 0
    current item is: 5
    current item is: 0
    current item is: 0
    current item is: 0
    current item is: 0
    current item is: 0
    current item is: 0
    current item is: 0

    2) 链表元素为结构体或结构体指针

    #include <iostream>
    #include <stdlib.h>
    #include <list>
    
    using namespace std;
    #pragma warning(disable:4996)
    
    
    struct Teacher {
        char name[20];
        int age;
    };
    
    
    // 使用迭代器遍历当前链表
    void printlist(list<Teacher*> &l)
    {
        for (list<Teacher*>::iterator p = l.begin(); p != l.end(); ++p)
        {
            Teacher *teacher = *p;
            cout << "Teacher, name is: " << teacher->name << ", age is: " << teacher->age << endl;
        }
    }
    
    
    // 使用迭代器遍历当前链表
    void printlist2(list<Teacher> &l)
    {
        list<Teacher>::iterator current = l.begin();                      // 返回第一个元素的迭代器,头指针,迭代器本质上就是一个指针
        while (current != l.end())                                          // l.end() 代表末尾迭代器 尾指针
        {
            Teacher teacher = *current;
            cout << "Teacher, name is: " << teacher.name << ", age is: " << teacher.age << endl;
            current++;
        }
    
    }
    
    
    
    int main() {
        
        Teacher t1, t2, t3;
        strcpy(t1.name,"jack");
        t1.age = 11;
        strcpy(t2.name,"mike");
        t2.age = 22;
        strcpy(t3.name,"tom");
        t3.age = 33;
    
        list<Teacher> l;
        l.push_back(t1);
        l.push_back(t2);
        l.push_back(t3);
    
        printlist2(l);
        
        printf("------------------指针元素-------------------
    ");
        list<Teacher *> m;
        m.push_back(&t1);
        m.push_back(&t2);
        m.push_back(&t3);
    
        printlist(m);
        
        system("pause");
        return 0;
    }

    运行结果:

    Teacher, name is: jack, age is: 11
    Teacher, name is: mike, age is: 22
    Teacher, name is: tom, age is: 33
    ------------------指针元素-------------------
    Teacher, name is: jack, age is: 11
    Teacher, name is: mike, age is: 22
    Teacher, name is: tom, age is: 33

  • 相关阅读:
    C#实现根据域名查询ip实例
    Ajax: 一个建立Web应用的新途径(转)
    CRC循环校验的具体算法(转)
    生成静态文件的新闻系统核心代码(.net C#)
    一个ajax的例子
    使用 JavaScript 实现 XMLHttpRequest,在IE,FireFox 上测试通过
    微软SQL Server 2005的30项顶尖特性(转)
    利用XMLHTTP无刷新自动实时更新数据(转)
    五子棋的核心算法(转)
    编写安全的SQL Server扩展存储过程(转)
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/7160271.html
Copyright © 2011-2022 走看看