数组、链表、栈、队列和STL

数组

数组是一种最基本的数据结构,它是内存上的一块连续存储空间。正因如此数组的随机访问很方便。但数组也有其固有的限制,大小分配后不能改变。

STL中的数组

STL中的Array是静态数组模板,就是我们所说的数组。使用方法如下。    

std::array<int, 3> a1 = { 1, 2, 3 };

std::array<std::string, 2>a3 = {"a","b"};

STL中的Vector是动态数组模板,根据需要动态的分配内存。Vector的采用加倍的扩容策略。Push_back()最坏情况,最好和平均情况是。数组和动态数组常用来组成更复杂的数据结构。

 

链表

链表是一种线性表(有n个元素组成的有限序列),链表是一种基础的数据结构,通常有一连串的节点组成。节点中存放数据和指向下一节点的指针。因为链表不是按线性的顺序存储结构,其查询某节点的时间是,插入操作。链表分为单链表,双链表和循环链表。

 

单链表

 

双链表

 

 

循环单链表

循环双链表

链表的性能比较

单链表和双链表的查询时间最好情况,最坏和平均情况。

单链表涉及到向前访问的操作Before(),InsertBefore(),Remove()最坏和平均情况,最好情况。其他查询更新操作。

双链表的所有操作都是。

STL中的链表

List是用普通双链表实现的,如果在实际应用中需要使用链表,那么首先应该选择List。或者将List作为其成员。

链表和数组的对比

数组

动态数组

链表

快速的随机访问

快速的随机访问

快速的插入和删除

大小受限

动态分配

容量不受限

插入删除费时

插入删除费时

随机访问慢

Forward_list是C++11添加的,实现为一种简单的单链表,没有size()成员,只有前向迭代器没有反向迭代器。

 

栈是一种后进先出的数据结构,可以用数组也可用链表实现。链表的实现形式更接近于栈的抽象概念,因为链表的节点数与栈中元素数目相同,而在数组实现形式中,数组的容量常常超过其尺寸。栈的直接应用包括函数调用,网页浏览记录,编辑器中的重做。。。栈也是其它数据结构和算法的基本组件。

顺序栈(用数组实现的栈)

链式栈(用链表实现的栈)

 

栈的性能比较

STL中的栈

STL中的stack是一种容器适配器,就是用其他容器最为底层实现,将其他容器转化为栈。Stack封装了入栈,出栈,取栈顶元素,查看大小和是否为空操作。默认情况下,stack用deque做底层容器。也可以将其修改为vector,list。

std::stack<int> deque_stack;

std::stack<int, std::vector<int>> vec_stack;

std::stack<int, std::list<int>> list_stack;

 

队列

队列是一种先进先出的数据结构,可以用数组也可以用链表实现队列。队列可用访问共享资源,排队购物。还用来构成其他更复杂的数据结构。

基于数组的队列

基于链表的队列

 

队列的性能分析

双端队列

双端队列的性能分析

优先队列

许多情况下队列的先入先出机制不能满足要求,此时需通过优先规则来完善入队出队的机制。优先队列应用而生。实现方式有两种:1.基于有序链表的实现,插入操作,删除操作;2.基于无序链表的实现,插入操作,删除操作。

 

堆(堆放在这里说是因为最大堆可用来实现优先队列)

堆是一种数据结构,完全二叉树,但在实现方式上没有选择一般的二叉树数据结构(即一个结点包含两个指向孩子的指针)而使用了数组。要明白堆的含义,必须知道什么是完全二叉树,完全二叉树是有满二叉树引起的,了解满二叉树也是必要的。

 

一般的树中,某结点的高度和深度的定义。

满二叉树: 如果一个二叉树的任意结点或者有0或者有2个孩子。

完全二叉树:如果一个二叉树除倒数第一层外都被填满,并且倒数第一层从左至右填充。

完美树:如果一个二叉树的所有层被填满。

堆的定义:1.是一个完全二叉树;2.上层的节点键值大于下层节点键值(最小堆),或者相反(最大堆)。

 

基于数组实现的堆

某节点位于数组i处,做左子节点位于2i,右子节点位于2i+1,数组第一个位置未使用。

STL中的队列

1.queue

STL中的queue是一种容器适配器,默认的底层实现容器是deque。这一点和stack很像,通过关闭或者限制deque的一些借口可以很轻松的实现stack和queue。Deque是stack和queue的幕后功臣。那么deque是怎么实现的?

2.deque

Deque是双端队列,它的空间构造是几块分段线性的存储区。其实现细节非常复杂。

Deque是如何扩展空间的?

如果缓冲区中还有备用的空间,那么直接使用备用的空间;否则,另外配置一个缓冲区,将其信息记录到缓冲区地址表里;更有甚者,如果缓冲区地址表都不够的时候,缓冲区地址表也要严格依从"重新配置,复制,释放"规则,但相比对"重新配置,复制,释放"规则宗教式追狂热的vector而言,效率高很多。侯杰老师推荐,将deque所有的元素倒腾到一个vector中,再用STL<algorithm>sort()函数,再从vector中倒腾进deque中。这种折腾是必须的,直接在的deque内部进行排序,效率更低。(引http://daoluan.net/blog/stl-deque/

3.priority_queue

Priority_queue优先级队列是一个拥有权值概念的单向队列queue,在STL的具体实现中也是以别的容器为底层数据结构,在利用堆的规则调整元素之间的位置。默认的底层实现是vector。这与queue的默认底层实现deque差别很大。

4.heap

STL中关于堆的操作,建堆make_heap(),加数据push_heap(),删数据pop_heap(),堆排序sort_heap()。头文件<algorithm>。

 

总结

数组

静态数组=array

动态数组=vector

链表

单链表= forward_list

双链表=list

队列

单向队列=queue(默认deque)

单向数组队列=queue<类型,vector<类型>>

单向链式队列=queue<类型,list<类型>>

双向队列=deque

优先队列=priority_queue(默认vector)

堆栈

meak_heap,push_heap,pop_heap,sort_heap

 

练习

1.手写堆

2.利用STL实现优先队列

posted @ 2014-02-26 10:37  tpys  阅读(4985)  评论(0编辑  收藏  举报