C++-list使用学习
###list(链表)是C++里面的一种容器,底层是双向的;
这就决定了它的迭代器使用的场景和能够使用的算法;双向(例如list)不能像随机(例如vector)那样用迭代器任意加上几去使用,list只能加加或者减减;
而对于按性质分类而不同类别的容器来说,它们能够使用的算法也是不一样的,随机性质的相当于具备其他性质的迭代器的特性,都可以使用,但是单向性质的只能使用单向的,同理双向性质的(list)则可以使用单向的和双向的,不能使用随机的
一、list的初始化
list初始化分为五种:
- 无参初始化,初始化的list对象为空;
- n个val去初始化;
- 利用容器对象的一段迭代器区间初始化;
- 拷贝初始化;
- 利用数组初始化。
###代码示例:
void test()
{
//list初始化
list<int> l1; //无参
list<int> l2(10, 1); //n个 val
list<int> l3(l2); //拷贝
list<int> l4(++l2.begin(), --l2.end()); //迭代器区间
cout << "l1:" << endl;
list_print(l1);
cout << "l2:" << endl;
list_print(l2);
cout << "l3:" << endl;
list_print(l3);
cout << "l4:" << endl;
list_print(l4);
int arr[10] = { 1,2,3,4,5 };
list<int> l5(arr, arr + sizeof(arr) / sizeof(arr[0])); //利用数组
cout << "l5:" << endl;
list_print(l5);
}
二、其他接口介绍
1、emplace_back和push_back的区别
emplace_back也是尾插数据,但是可以直接传值去尾插,这样省去来拷贝构造的步骤,有一点优化;而push_back不能直接传值去初始化;
###代码示例:
void test()
{
list<A> l1;
l1.push_back(A(2, 2.2));
cout << "****************" << endl;
list<A> l2;
l2.emplace_back(2, 2.2);//可以直接给值
}
2、insert和erase
insert:
- 用迭代器指定一个位置,在此位置之前插入数据;(返回值是指向原来数据的迭代器)
- 在指定位置之前插入n个数据;
- 在指定位置插入一段迭代器区间内的数据,这个迭代器可是不同的容器。
void test()
{
list<int> mylist;
for (int i = 1; i < 5; i++)
{
mylist.push_back(i); //1 2 3 4 5
}
list<int> :: iterator it = mylist.begin();
it++;//现在指向 mylist 里面的数据2
mylist.insert(it, 99);//1 99 2 3 4 5 现在it还是指向2
mylist.insert(it, 9);
list_print(mylist);
it--;//指向9
mylist.insert(it, 3, 0);//插入三个0;
list_print(mylist);
vector<int> v(3, 100);
mylist.insert(mylist.begin(), v.begin(), v.end());//插入一段迭代器区间的数据
list_print(mylist);
}
erase:
- 删除指定位置的数据,返回值是指向这个待删除元素之后的下一个数据的迭代器,若是这个待删除的数据为list里面的最后一个数据,那么返回值就是list的end;
- 删除一段迭代器区间的数据。
void test()
{
list<int> mylist;
for (int i = 1; i <= 5; i++)
{
mylist.push_back(i); //1 2 3 4 5
}
list<int> ::iterator it = mylist.begin();
it = mylist.erase(it);//删除it处的数据 :2 3 4 5
cout << *it << endl;
list_print(mylist);
mylist.insert(mylist.begin(), 1);//恢复
it = mylist.begin();
it++;
it++;//现在指向3
it = mylist.erase(mylist.begin(),it);
cout << *it << endl;
list_print(mylist);
}
3、unique(去重)
- 无参的:删除一串连续数据里面除了第一个以外的其他的相同的元素;只有当这个元素前面的元素和它相同时才会删除这个元素,也就是说,这个函数用于有序的数据;
void test()
{
list<int> mylist;//有序
mylist.push_back(1);
mylist.push_back(1);
mylist.push_back(2);
mylist.push_back(3);
mylist.push_back(4);
mylist.push_back(4);
list_print(mylist);
mylist.unique();
list_print(mylist);
list<int> mylist1;//无序
mylist1.push_back(1);
mylist1.push_back(2);
mylist1.push_back(3);
mylist1.push_back(2);
mylist1.push_back(5);
mylist1.push_back(4);
list_print(mylist1);
mylist1.unique();
list_print(mylist1);
}
只有一个元素前面的元素和它一样时,才会删除这个元素。
4、remove
删除list里面与指定的val值相同的元素,有多少个就删除多少个;
void remove_test()
{
int arr[] = { 1,22,3,88,9,3};
list<int> mylist(arr, arr + sizeof(arr) / sizeof(arr[0]));
list_print(mylist);
mylist.remove(3);
list_print(mylist);
}
5、merge
整合一个list(A)进入另一个list(B),这两个list都必须是有序的,整合的数据从左到右升序排列,整合完之后A为kong,B中数据增加,但是这些操作不涉及到数据的创建和销毁,只是转移;
void merge_test()
{
list<double> first, second;
first.push_back(2.1);
first.push_back(6.1);
first.push_back(4.1);
second.push_back(3.1);
second.push_back(1.1);
second.push_back(5.1);
list_print(first);//初始序列打印
list_print(second);
first.sort();
second.sort();
list_print(first);//排序之后打印
list_print(second);
first.merge(second);
list_print(first);//整合之后打印
list_print(second);
}
6、vector和list的sort的比较
vector用sort比list用sort更快
void sort_comp()
{
srand((unsigned)time(NULL));
list<int> my_list;
vector<int> my_vector;
for (int i = 0; i < 1000000; i++)
{
int a = rand() % 1000000;
my_list.push_back(a);
my_vector.push_back(a);
}
clock_t start1 = clock();
my_list.sort();
clock_t end1 = clock();
int rsl1 = (int)(end1 - start1);
clock_t start2 = clock();
sort(my_vector.begin(),my_vector.end());
clock_t end2 = clock();
int rsl2 = (int)(end2 - start2);
cout << "list_sort:" << rsl1 << endl;
cout << "vector_sort::" << rsl2 << endl;
}