QList 和std::list的比较

来源:互联网 发布:手机淘宝 假的 编辑:程序博客网 时间:2024/06/10 03:17

QList

QList<T> 是一个Qt通用容器类。它存储一序列的值,并且提供基于索引的数据访问方法和快速的插入和删除操作。

QList<T>, QLinkedList<T>, QVector<T>提供类似的功能,这里进行几点概述:

1.     大多数情况下,最好使用QList。它基于索引的APIQLinkedList基于迭代器的API方便。它存储数据的方式也使得它比QVector存取数据的数度快。而且它在可执行文件中扩展的代码也比较少。

2.    需要一个真正的链表,能保证在中间插入数据的时间复杂度是常量的,用迭代器来存钱元素的,那可以用QLinkedList

3.     如果想容器的元素在相邻的内存,可以用QVector

在内部,QList<T>是一个指向T类型的指针数组。如果T本身是一个指针类型或者不大于指针的基本数据类型,或者如果T是一个Qt共享类,QList<T>在直接将元素保持在指针数组中。对于少于一千个元素的链表,这样的数组表示允许在中间快速的插入,而且运行基于索引的存钱方法。此外,prepend() and append() 操作速度也很快,因为QList在其内部数组的两端预先分配了内存。需要注意的是,对于大于指针的非list项,每次append insert新的项都需要在堆上分配内存,如果需要这样的大量的插入和添加操作,这时最好选择QVector,因为QVector在单一的堆上分配内存。

 

需要注意的是:在list的生命期中,内部数组只有可能变大,不可能缩小。内部数组只能有析构函数释放或者当用一个list赋值给另外的list时,由赋值函数释放。

 

为了使QList尽可能高效,它的成员函数不验证输入的有效性。除了isEmpty()之外,其他的成员函数都假定list是非空的。使用索引参数的成员函数总是假定索引值是在有效的范围的。这意味着QList的函数可能调用失败。如果你在编译时定义了QT_NO_DEBUG,则将不会捕获这样的失败。如果没有定义QT_NO_DEBUG Q_ASSERT() or Q_ASSERT_X() 将捕获这些失败弹出适当的信息。

 

为了避免失败,在调用其他成员函数前调用isEmpty()。如果成员函数用到索引参数,要检查索引是否在有效的范围。

QVector类似,QList也是用的隐式共享。

 

QList<int>integerList;

integerList.push_back(1);

integerList.append(5);

 

//integerList.setSharable(false);

QList<int>List(integerList);

//List= integerList;

//integerList.setSharable(false);

 

cout<<"&List.at(0):"<<&List.at(0)<<endl;

cout<<"&integerList.at(0):"<<&integerList.at(0)<<endl;

integerList.setSharable(false);取消注释之后显示的地址就不一样了


 

std::list

std::list是一种顺序容器,它允许在其中的任何位置进行插入和删除操作,而且可以双向迭代。

List容器实现为双向链表,双向链表可以在不同而且不相关的位置进行存储其元素。其关联的顺序由一个指向前面元素的链接和一个指向后面元素的链接来保持的。

List类似于forward_list。最主要的不同就是forward_list是单链表,所以它只能前向迭代,因此也更小和更高效。

和其他基本的标准容器 (arrayvector and deque)相比,list在插入,提取,移动数据方面更高效,因此在密集的算法中一般都用list,比如排序算法。

和其他顺序容器相比,listsand forward_lists最大的缺点就是缺少通过位置直接存取元素的方法;它们也需要额外的内存来保持链接的信息。

QList 和std::list比较

构造函数:

QList构造函数:

QList::QList ()

QList::QList ( constQList<T> & other )

 

List构造函数:

C++98版:

explicit list (constallocator_type& alloc = allocator_type());

explicit list (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());
template <class InputIterator> list (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
list (const list& x);

 

C++11版:

explicit list (const allocator_type& alloc = allocator_type());
explicit list (size_type n); 
list (size_type n, const value_type& val,  const allocator_type& alloc = allocator_type());
template <class InputIterator> list (InputIterator first, InputIterator last,
                                    const allocator_type& alloc = allocator_type());
list (const list& x);
list (const list& x, const allocator_type& alloc);
list (list&& x);
list (list&& x, const allocator_type& alloc);
list (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());

QList的构造函数只有默认构造函数和拷贝构造函数两种,std::list的构造函数就比较多了。

 

QList特有的函数:

void QList::append ( const T & value )          在链表的末尾插入value

void QList::append ( constQList<T> & value )    在链表的末尾插入链表value的元素

该函数实际上调用了QList<T> &

operator+= ( const QList<T> & other )

 

bool QList::contains ( const T& value ) const     判断链表是否包含元素value

int QList::count ( const T& value ) const         统计链表中值为balue的元素个数

void QList::move ( int from,int to )   把索引为from的值移到索引为to的位置

 

QList<QString> list;

 list << "A" <<"B" << "C" << "D" <<"E" << "F";

 list.move(1, 4);

 // list: ["A", "C","D", "E", "B", "F"]

有关删除的一些操作:

 

void QList::removeAt (int i )

bool QList::removeOne ( const T & value )

void QList::removeFirst ()

void QList::removeLast ()

T QList::takeAt ( int i )

T QList::takeFirst ()

T QList::takeLast ()

 

与其他类型容器的转换方式:

QSet<T> QList::toSet () const

std::list<T> QList::toStdList ()const

QVector<T> QList::toVector () const

 

支持的操作符运算:

bool QList::operator!= ( constQList<T> & other ) const

QList<T> QList::operator+ (const QList<T> & other ) const

QList<T> & QList::operator+=( const QList<T> & other )

QList<T> & QList::operator+=( const T & value )

QList<T> &QList::operator<< ( const QList<T> & other )

QList<T> &QList::operator<< ( const T & value )

QList<T> & QList::operator=( const QList<T> & other )

bool QList::operator== ( constQList<T> & other ) const

T & QList::operator[] ( int i )

const T & QList::operator[] ( int i ) const

 

QDataStream & operator<< ( QDataStream & out, const QList<T> & list )

QDataStream & operator>> ( QDataStream & in, QList<T> & list )

 

Std::list特有的函数:

SpliceC++98版:

void splice (iterator position, list& x);
void splice (iterator position, list& x, iterator i);
void splice (iterator position, list& x, iterator first, iterator last);

C++11版:

void splice (const_iterator position, list& x);
void splice (const_iterator position, list&& x);
void splice (const_iterator position, list& x, const_iterator i);
void splice (const_iterator position, list&& x, const_iterator i);
void splice (const_iterator position, list& x, const_iterator first, const_iterator last);
void splice (const_iterator position, list&& x, const_iterator first, const_iterator last);

该函数个功能是:把链表x的元素,从x中转移到该链表中,从位置position进行插入。该操作不会调用任何元素的构造函数或析构函数。会同时改变这两个链表的大小。

std::list<int>mylist1, mylist2;

std::list<int>::iteratorit;

for(int i=1; i<=4; ++i)

         mylist1.push_back(i);   

for(int i=1; i<=3; ++i)

         mylist2.push_back(i*10); 

it =mylist1.begin();

++it;                       

mylist1.splice(it, mylist2);

cout<<"mylist1.size():"<<mylist1.size()<<endl;

cout<<"mylist2.size():"<<mylist2.size()<<endl;

it =mylist1.begin();

cout<<"mylist1:";

for(it; it !=mylist1.end(); ++it)

{

         cout<<*it<<" ";

}

cout<<endl;

it =mylist2.begin();

cout<<"mylist2:";

for(it; it !=mylist2.end(); ++it)

{

         cout<<*it<<" \t";

}

 

sort操作

void sort();
template <class Compare>
  void sort (Compare comp);
版本1用的是 < 比较操作,版本2用comp 进行比较。这两个排序进行的是严格的弱排序。对与相同的值是稳定的,排序后相对位置不变。元素在容器中进行移动,整个过程不会调用任何构造函数,析构函数或拷贝任何元素。

 

Unique操作:

void unique();
template <class BinaryPredicate>
  void unique (BinaryPredicate binary_pred);
不带参数的版本1会删除每一组相同值的除了第一个元素之外的元素,例如,有连续的几个值为 a  a  a,它会删除后面的两个a,值保留第一个a。
版本2用binary_pred作为比较函数,需要注意的是,该函数会为每个比较对调用binary_pred(*i,*(i-1)),如果比较返回true则会从链表中删除i

boolsame_integral_part (double first, double second)

{

         return ( int(first)==int(second) );

}

structis_near

{

         bool operator() (double first, doublesecond)

         {

                   return(fabs(first-second)<5.0);

         }

};

 

         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();            

         std::list<double>::iterator it =mylist.begin();

         cout<<"after sort() mylist:";

         int i = 0;

         for (it; it != mylist.end(); ++it, ++i)

         {

                   cout<<*it<<"  ";

                   if (i == 5)

                   {

                            cout<<endl;

                   }

         }

         cout<<endl;

 

         mylist.unique();

         it = mylist.begin();

         cout<<"after unique() mylist:";

         for (it; it != mylist.end(); ++it)

         {

                   cout<<*it<<"  ";

         }

         cout<<endl;

         mylist.unique (same_integral_part);

         it = mylist.begin();

         cout<<"after unique(same_integral_part) mylist :";

         for (it; it != mylist.end(); ++it)

         {

                   cout<<*it<<"  ";

         }

         cout<<endl;

 

         mylist.unique (is_near());         

         it = mylist.begin();

         cout<<"after unique(same_integral_part) mylist :";

         for (it; it != mylist.end(); ++it)

         {

                   cout<<*it<<"  ";

         }

         cout<<endl;

 

merge 操作:

C++98版本:
void merge (list& x);
template <class Compare>
  void merge (list& x, Compare comp);
 
C++11版本:
void merge (list& x);
  void merge (list&& x);
template <class Compare>
void merge (list& x, Compare comp);
template <class Compare>
  void merge (list&& x, Compare comp);
该函数把x的元素按适当的顺序合并到链表中,前提是两个链表都是已经排序了的。
该操作会移除x中的元素插入到链表中,和splice一样,它不会调用构造函数或者析构函数,仅仅是做了转移而已。
版本2指定了一个比较操作函数,它对元素进行严格的弱排序。调用该函数,链表必须是已经排序的,对于没有排序的链表,可以用splice。
对于相同的值也是稳定的,其位置和在x中的相对位置一样。

boolmycomparison (double first, double second)

{

         return ( int(first)<int(second) );

}

 

std::list<double>first, second;

         first.push_back (3.1);

         first.push_back (2.2);

         first.push_back (2.9);

 

         second.push_back (3.7);

         second.push_back (7.1);

         second.push_back (1.4);

 

         first.sort();

         second.sort();

 

         first.merge(second);

         // (second is now empty)

         second.push_back (2.1);

         first.merge(second,mycomparison);

         std::cout << "after mergefirst contains:";

         for (std::list<double>::iteratorit=first.begin(); it!=first.end(); ++it)

                   std::cout << ' '<< *it;

         std::cout << '\n';

         std::cout << "after mergesecond contains  size:"<<second.size()<<endl;


如果我们尝试把排序的两句代码注释掉,则会弹出失败的断言信息。在merge函数中会检查链表是否已经排序。

first.sort();

second.sort();

 

reverse操作:

C++98版本:

void reverse();

C++11版本:

void reverse() noexcept;

该函数对链表进行反转。

std::list<int>mylist;

         for (int i=1; i<10; ++i)

                   mylist.push_back(i);

         std::cout << " beforereverse mylist contains:"<<endl;

         for (std::list<int>::iteratorit=mylist.begin(); it!=mylist.end(); ++it)

                   std::cout << ' '<< *it;

         std::cout << '\n';

         mylist.reverse();

         std::cout << "after reversemylist contains:"<<endl;

         for (std::list<int>::iteratorit=mylist.begin(); it!=mylist.end(); ++it)

                   std::cout << ' '<< *it;

         std::cout << '\n';

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 西装裤裤脚太宽怎么办 全棉衣服有异味怎么办 羊剪绒毛领褪色怎么办 篮球鞋买大2码怎么办 新鞋穿着脚累怎么办 买了国产乔丹怎么办 跑完1000米吐了怎么办 翻毛鞋脚染色了怎么办 翻毛皮被染色了怎么办 防鹿皮绒鞋染色怎么办 亚瑟士跑鞋挤脚怎么办 亚瑟士跑鞋很紧怎么办 飞线鞋面破了怎么办 新袜子穿了很滑怎么办 鞋底硬脚底板疼怎么办 新鞋前面太硬怎么办 新鞋子鞋底太硬怎么办 不到一米八的身高想扣篮怎么办 鞋胶粘在鞋面上怎么办 鞋子上沾了胶怎么办 休闲鞋号码大了半码怎么办 高跟鞋大了一码怎么办 浅口单鞋买大了怎么办 新鞋子磨大脚趾怎么办 鞋前面磨大脚趾怎么办 白鞋子蹭黑了怎么办 夏天穿皮鞋捂脚怎么办 耐克赤足掉漆怎么办 鞋子买回来小了怎么办 布鞋大了一码怎么办 鞋子买小了一码怎么办 运动鞋小了一码怎么办 帆布鞋小了一码怎么办 脚踝骨韧带断了怎么办 咖啡喝多了失眠怎么办 奥迪q7电瓶没电怎么办 一岁宝宝坐不稳怎么办 2岁宝宝不肯把尿怎么办 踢足球上肢和下肢不协调怎么办 ppt文字放映时重叠怎么办 月子8天腰背疼怎么办