1. 程式人生 > >4.lists(雙向鏈表)

4.lists(雙向鏈表)

swa 內存空間 不能 素數 mes 結構體 常用api 內存大小 disable

一.概述

  是一個線性鏈表結構,它的數據由若幹個節點構成,每一個節點都包括一個信息塊(即實際存儲的數據)、一個前驅指針和一個後驅指針。它無需分配指定的內存大小且可以任意伸縮,這是因為它存儲在非連續的內存空間中,並且由指針將有序的元素鏈接起來。由於其結構的原因,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("----------------------------------------\n");

    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("------------------指針元素-------------------\n");
    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

4.lists(雙向鏈表)