数据结构与STL容器
一、
1、线性表
线性表包括顺序存储结构(用一段连续地址存储)和链式存储结构(数据域+指针域)。顺序存储结构的代表是C/C++中的数组,其读时间复杂度为O(1),插入/删除为O(n),因为从插入/删除位置到最后一个元素都要向前/后移动一个位置。链式存储结构包括单链表(普通链表)、循环链表、双向链表等,单链表的读取为O(n),插入/删除O(n)——不清楚第i个元素指针位置时,但是已知时为O(1),代表为list容器。
2、栈
属于特殊的线性表,它一种先进后出的数据结构,代表为STL的stack。
3、队列
属于特殊的线性表,它一种先进先出的数据结构,代表为queue。
4、树
分为二叉树和多叉树(N叉树),map和set内部使用红黑树结构,在最坏的情况下查找、插入和删除仅消耗对数时间log(n)。
5、哈希表
STL中的unorder_map和unorder_set使用的就是hash table结构,查找、插入和删除消耗为常数级别O(1)。
二、
1、静态数组
静态数组就是大小固定不能扩展的数组,如C中普通数组、C++11中array。
2、动态数组
动态数组的空间大小在需要的时候可以进行再分配,其代表为vector。由于数组的特点,在位置0插入需要将整个数组后移一个位置来腾出空间,删除位置0的元素则需要将剩余元素前移一个位置,这两种最坏的情况为O(n)。所以vector只适合在末尾添加或删除元素,使用[]或迭代器随机访问是快速的。
deque可以可以看作是vector的增强版,它增加了在头部快速插入和删除元素。
3、链表
链表由一系列不必在内存中相连的结点组成,每个结点包含了结点元素和到后继结点的链。链表避免了插入和删除的线性开销,但随机访问效率很低。使用链表结构的代表是list容器,而且list是基于双向链表实现的。下图是普通链表与双向链表的示意图:
4、栈
栈的特点是后进先出,位于栈顶的元素是唯一可见的元素。栈可以使用链表来实现,通过在链表顶端插入元素来实现push,通过删除链表顶端元素来实现pop,top操作返回顶端元素。c++中栈数据结构的实现是容器适配器stack,stack其所关联的基础容器可以为vector、list、deque,默认为deque。
5、队列
队列的特点是先进先出,队列也可以使用链表来实现,enqueue(入队)是在链表的末端插入一个元素,dequeue(出队)是删除并返回链表开头的元素。c++中队列数据结构的实现是容器适配器queue,其所关联的基础容器可以为list或deque,默认为deque。
6、链表的创建和操作
typedef struct node
{
int iIndex;
struct node* pNext;
}Node, *NodePtr; //创建链表
NodePtr CreateList(unsigned iLen)
{
NodePtr pHeadNode = NULL, pLastNode = NULL;
for (unsigned i = ; i < iLen; i++)
{
NodePtr pNode = new Node;
pNode->iIndex = i;
if (pLastNode)
pLastNode->pNext = pNode;
else
pHeadNode = pNode; pLastNode = pNode;
}
pLastNode->pNext = NULL; return pHeadNode;
} //输出链表
void PrintList(NodePtr pHeadNode)
{
NodePtr pNode = pHeadNode;
do
{
cout << pNode->iIndex << ", ";
pNode = pNode->pNext;
} while (pNode); cout << endl;
} //链表排序:利用选择排序法思想
void SelectSortList(NodePtr pHeadNode)
{
NodePtr pNode = pHeadNode;
while (pNode->pNext)
{
NodePtr pNodeMin = pNode;
NodePtr pNodeNext = pNode->pNext;
while (pNodeNext)
{
if (pNodeNext->iIndex < pNodeMin->iIndex)
pNodeMin = pNodeNext; pNodeNext = pNodeNext->pNext;
} if (pNodeMin != pNode)
swap(&pNode->iIndex, &pNodeMin->iIndex); pNode = pNode->pNext;
}
} //合并两个有序链表为一个
NodePtr UnionList(NodePtr pHeadNode1, NodePtr pHeadNode2)
{
NodePtr pHeadNode = new Node;//新的链表添加一个头结点
NodePtr pNode1 = pHeadNode1, pNode2 = pHeadNode2, pNode = pHeadNode; while (pNode1 && pNode2)
{
if (pNode1->iIndex <= pNode2->iIndex)
{
pNode->pNext = pNode1;
pNode = pNode->pNext;
pNode1 = pNode1->pNext;
}
else
{
pNode->pNext = pNode2;
pNode = pNode->pNext;
pNode2 = pNode2->pNext;
}
} pNode->pNext = pNode1 ? pNode1 : pNode2;//插入剩余段 NodePtr pReturnNode = pHeadNode->pNext;
delete pHeadNode;//删除新链表的头结点
return pReturnNode;
} //链表逆序:定义三个节点指针分别指向前三个节点,第二个节点的pNext重新指向第一个节点,三个节点指针再往后移动,如此往复
NodePtr TurnList(NodePtr pHeadNode)
{
if (pHeadNode->pNext)
{
NodePtr pLastNode = pHeadNode;
NodePtr pNode = pLastNode->pNext;
NodePtr pNextNode = pNode->pNext; while (pNextNode)
{
pNode->pNext = pLastNode; pLastNode = pNode;
pNode = pNextNode;
pNextNode = pNextNode->pNext;
} pNode->pNext = pLastNode;
pHeadNode->pNext = NULL; return pNode;
}
else
return pHeadNode;
}
三、
1、顺序容器:
vector为向量容器,支持使用下标来快速随机访问(所以提供了[]和at()访问元素的方法,迭代器支持++、--、+=、-=算数操作),支持在尾部快速插入、删除元素,不支持在头部或中间快速插入数据(因为这样会导致重新分配整个内存)。
list为链表容器,支持在容器头、尾、内部快速插入、删除元素(插入、删除不会重新分配内存),不支持快速随机访问(不提供[]或at()来访问元素,仅提供迭代器的++、--算数操作,使用find()查找元素会很慢)。
虽然list的迭代器不提供+、-、+=、-=操作,但其实可以通过advance、next/prev方法来实现这些操作,但是通过这些方法获得的list的迭代器进行distance操作的话会出错,所以如果要对list进行advance、next等操作的话应该想一想使用的容器是不是改成vector更合适:
std::list<int> myList = {, , , , }; auto it = myList.begin();
std::advance(it, ); //advance移动当前迭代器
int n = *it; // auto it2 = std::next(myList.begin(), ); //next/prev获得迭代器之后/之前的迭代器,不改变当前迭代器
n = *it2; // n = std::distance(myList.begin(), myList.end()); //5,distance获得迭代器之间的距离
n = std::distance(it, it2); //error
queue队列,适合队尾插入元素,队头删除元素的情况,它是容器适配器,其所关联的基础容器可以为list或deque,默认为deque。
deque为双端队列,它可以看作是queue的增强版,其支持在头部和尾部快速插入和删除元素。
priority_queue为优先级队列,允许设置元素的优先级,将新的元素放置在比它优先级低的元素前面,要求提供随机访问的功能,所以其所关联的基础容器可以为vector、deque,默认基础容器为vector
stack栈,适合后进先出的情况,它是容器适配器,其所关联的基础容器可以为vector、list、deque,默认为deque
2、关联容器
map、unordered_map、multimap为映射容器,支持通过键来快速查找和读取元素,其元素为键-值对的形式,键相当于元素的索引,值为元素所存储的数据。当使用下标[]来引用映射容器内元素的时候如果当前容器内没有该键则会自动创建该键值对。map元素是排序的,multimap支持同一个键多次出现。
set、multiset为集合容器,其元素仅包含一个键,有效的支持某个键是否存在的查询。set中元素是排序的,multiset支持同一个键多次出现。
3、vector等容器对于元素的要求是可复制和可赋值,map容器的key还需要支持<比较操作,所以如果把自定义类型作为map的key的话需要重载<,如:
struct Data
{
int i;
bool operator<(const Data& d)const
{
return i < d.i;
}
};
数据结构与STL容器的更多相关文章
- STL容器底层数据结构的实现
C++ STL 的实现: 1.vector 底层数据结构为数组 ,支持快速随机访问 2.list 底层数据结构为双向链表,支持快速增删 3.deque ...
- STL容器的本质
http://blog.sina.com.cn/s/blog_4d3a41f40100eof0.html 最近在学习unordered_map里面的散列函数和相等函数怎么写.学习过程中看到了一个好帖子 ...
- STL容器是否是线程安全的
转载http://blog.csdn.net/zdl1016/article/details/5941330 STL的线程安全. 说一些关于stl容器的线程安全相关的话题. 一般说来,stl对于多线程 ...
- STL容器总结
一. 种类: 标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope.sl ...
- STL容器之优先队列(转)
STL容器之优先队列 原地址:http://www.cnblogs.com/summerRQ/articles/2470130.html 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关 ...
- STL容器之优先队列
STL容器之优先队列 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关键字是priority_queue(太伤了).在一些定义了权重的地方这个数据结构是很有用的. 先回顾队列的定义:队列 ...
- 关于STL容器
容器: 概念:如果把数据看做物体,容器就是放置这些物体的器物,因为其内部结构不同,数据摆放的方式不同,取用的方式也不同,我们把他们抽象成不同的模板类,使用时去实例化它 分类: 序列容器.关联容器.容器 ...
- STL 容器简介
一.概述 STL 对定义的通用容器分三类:顺序性容器.关联式容器和容器适配器. 顺序性容器是一种各元素之间有顺序关系的线性表.元素在顺序容器中保存元素置入容器时的逻辑顺序,除非用删除或插入的操作改变这 ...
- STL 容器的概念
STL 容器的概念 在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要求很高的部分时,数据结构的选择就显得更加重要. 经典的数据结构数量有限,但是我们 ...
随机推荐
- layui时间控件,获取页面选中的时间值。
先贴上html文档 <div class='layui-form'> <div class="layui-form-item"> <div class ...
- linux下压力测试工具ab的使用
一.安装 [root@node2 logs]# yum install httpd-tools 已加载插件:fastestmirror Loading mirror speeds from cache ...
- day49 定位布局和过渡动画
复习 1.盒子在父级水平居中 margin: 0 auto; 2.文本样式操作 color: red; text-align: center; font: 900 30px/200px "S ...
- springboot+dubbo提示超时
在消费方工程的application.properties里面加上dubbo.consumer.timeout=30000.
- innodb_flush_log_at_trx_commit与sync_binlog理解
innodb_flush_log_at_trx_commit该参数控制重做日志写入磁盘的过程.我们知道 InnoDB 使用“Write Ahead Log”策略来避免数据丢失问题,即依靠重做日志来保证 ...
- 18. 4Sum (JAVA)
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums s ...
- vue 配置了全局的http拦截器,单独某个组件不需要这个拦截器,如何设置
之前写过关于全局配置http拦截器的随笔,现在有个需求,在微信支付时,生成二维码,页面显示一个遮罩层,二维码页面需要每两秒请求一次接口,若返回结果为已支付,则进行页面跳转,但因为全局http中load ...
- Python基础-文件操作(七)
一.文件基本操作 1.open 打开模式: w模式 写模式write 文件不存在时会创建文件,如果文件已存在则会清空文件 r模式 读模式read 文件不存在就报错,存在则准备读取文件 a模式 追加模式 ...
- mysql学习记录
干净卸载mysql:https://blog.csdn.net/cxy_summer/article/details/70142322mysql 解压缩版安装说明:https://jingyan.ba ...
- SQLServer 中有五种约束, Primary Key 约束、 Foreign Key 约束、 Unique 约束、 Default 约束和 Check 约束
一直在关注软件设计方面,数据库方面就忽略了很多,最近在设计数据库时遇到了一些小麻烦,主要是数据库中约束和性能调优方面的应用,以前在学习 Sql Server 2000,还有后来的 Sql Server ...