-
线性表的两种描述:数组/向量描述、链式描述,STL中的vector和list大致相当于这两种描述方法。
·数组/向量描述:所有元素依次存储在一片连续的存储空间中(静态存储)。
·链式描述:元素在内存中的存储位置是随机的(动态存储),每个元素都有一个明确的指针指向下一个元素的地址。 -
STL vector的使用
·使用前应包含头文件和命名空间:
#include <vector>
using namespace std::vector
·创建和初始化:
vector<int> vec1;//默认构造函数,vec1为空
vector<int> vec2(size);//vec2初始化为size个元素,默认值是0
vector<int> vec3(size,value);//vec3初始化为size个值为value的向量
vector<int> vec4(vec3);//vec4是vec3的一个副本
vector<int> vec5(iter1,iter2);//用迭代器iter1和iter2之间的元素创建vec5
vector<int> vec6{1,2,3,4,5,6,7};//vec6用列表初始化
·容量和大小
auto length = vec.size();
vec.reserve(100);//容量增至100
auto cap = vec.capacity();
vec.empty();//若向量为空则返回true
vec.resize(n);//将长度改为n,超出的元素被删除
vec.resize(n,m);//长度改为n,超出的元素设为m
·元素的访问
vec[1] = 5;//使用索引访问
vec.at(1) = 5;//与[]用法相同,但可以检查越界
vec.front();//返回向量中第一个元素的引用
vec.back();//返回向量中最后一个元素的引用
vec.begin();//返回向量中第一个元素的迭代器
vec.end();//返回向量中最后一个元素的下一个位置的迭代器,仅作结束游标,不可解引用
vec.rbegin();//返回一个反向迭代器,该迭代器指向容器的最后一个元素
vec.rend();//返回一个反向迭代器,该迭代器指向容器第一个元素前面的位置
·元素的添加
vec.push_back(x);//把x插入到向量的尾部
vec.insert(iter,x);//在迭代器iter指向的元素之前插入值为x的新元素,返回指向新插入元素的迭代器
vec.insert(iter,n,x);//在迭代器iter指向的元素之前插入n个值为x的新元素,返回void
vec.insert(iter,start,end);//把迭代器start和end所指定的范围内的所有元素插入到迭代器iter所指元素之前,返回void
·元素的删除
vec.clear();//删除所有元素
vec.pop_back();//删除向量尾部的元素
vec.erase(iter);//删除迭代器iter所指向的元素,返回一个迭代器,指向被删除元素后面的元素
vec.erase(start,end);//删除迭代器start、end所指定范围内的元素,返回一个迭代器,指向被删除元素段后面的元素
·其他
vec.swap(vec2);//交换两个向量的内容
vec.reverse();//反转元素顺序
- STL list(双向链表)的使用
·使用前应包含头文件和命名空间:
#include <list>
using namespace std::list
·创建和初始化:
list<int> lst1;//默认构造函数,lst1为空
list<int> lst2(size);//lst2初始化为size个元素,默认值是0
list<int> lst3(size,value);//lst3初始化为size个值为value的链表
list<int> lst4(lst3);//lst4是lst3的一个副本
list<int> lst5(iter1,iter2);//用迭代器iter1和iter2之间的元素创建lst5
list<int> lst6{1,2,3,4,5,6,7};//lst6用列表初始化
·容量和大小
auto length = lst.size();
lst.empty();//若链表为空则返回true
lst.resize(n);//将长度改为n,超出的元素被删除
lst.resize(n,m);//长度改为n,超出的元素设为m
·元素的访问
//list无法使用索引访问
lst.front();//返回链表中第一个元素的引用
lst.back();//返回链表中最后一个元素的引用
lst.begin();//返回链表中第一个元素的迭代器
lst.end();//返回链表中最后一个元素的下一个位置的迭代器,仅作结束游标,不可解引用
lst.rbegin();//返回一个反向迭代器,该迭代器指向容器的最后一个元素
lst.rend();//返回一个反向迭代器,该迭代器指向容器第一个元素前面的位置
·元素的添加
lst.push_front(x);//把x插入到链表的头部
lst.push_back(x);//把x插入到链表的尾部
lst.insert(iter,x);//在迭代器iter指向的元素之前插入值为x的新元素,返回指向新插入元素的迭代器
lst.insert(iter,n,x);//在迭代器iter指向的元素之前插入n个值为x的新元素,返回void
lst.insert(iter,start,end);//把迭代器start和end所指定的范围内的所有元素插入到迭代器iter所指元素之前,返回void
·元素的删除
lst.clear();//删除所有元素
lst.pop_back();//删除链表头部的元素
lst.pop_back();//删除链表尾部的元素
lst.erase(iter);//删除迭代器iter所指向的元素,返回一个迭代器,指向被删除元素后面的元素
lst.erase(start,end);//删除迭代器start、end所指定范围内的元素,返回一个迭代器,指向被删除元素段后面的元素
lst.remove(m);//删除元素m
lstt.unique();//删除连续重复元素
·其他
lst.swap(lst2);//交换两个链表的内容
lst.reverse();//反转元素顺序
-
线性表的链式存储结构
·头指针:链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。无论链表是否为空,头指针均不为空。头指针是链表的必要元素。
·头结点:放在第一元素的结点之前,其数据域一般无意义(也可存放链表的长度)。有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其它结点的操作就统一了。头结点不一定是链表必须要素。 -
单链表结构和顺序存储结构的时间性能对比
·查找:顺序存储结构O(1)、单链表O(n)。
·插入和删除:顺序存储结构需要平均移动表长一半的元素,时间为O(n);单链表在线出某位置的指针后,插入和删除时间仅为O(1)。 -
静态链表:用数组描述的链表。
数组的元素都是由两个数据域组成,data和cur。数组的每个下标都对应一个data和一个cur。数据域data,用来存放数据元素;而游标cur相当于单链表中的next指针,存放该元素的后继在数组中的下标。 -
循环链表:将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表。
-
双向链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域。故双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱。