`
evasiu
  • 浏览: 169485 次
  • 性别: Icon_minigender_2
  • 来自: 广州
博客专栏
Fa47b089-e026-399c-b770-017349f619d5
TCP/IP详解卷一>阅读...
浏览量:12549
社区版块
存档分类
最新评论

stl中的几个精美算法

 
阅读更多
关于STL中的算法,我印象比较深刻的主要有用于list的sort、power以及用于random_access_iterator的qsort,list是一种bidirectional_iterator,因此设计了自己的一个sort算法,主要思想是mergesort。

首先看一下list中的sort:

template<class T, class Alloc>
void list<T, Alloc>::sort(){
	//这一段主要用于判断列表是否为空,或者只有一个节点
	if( node->next == node || link_type(node->next)->next == node )
		return;
	//一些新的lists,用于作为mergesort的中转区
	list<T, Alloc> carry;		//听这两个名字,就像二进制中的加减计算器,事实上我感觉跟它是有点关系的
	list<T, Alloc> counter[64];	//counter[i]里存放2^i个元素
	int fill = 0;			//fill用于记录到目前为止counter中不为空的那个最大的counter[i]的下标i+1(好绕啊)
	while( !empty() ){
		//把链表的头一个元素放到carry中去,作为carry的头一个元素
		//每次这个时候,carry都是为空的
		carry.splice( carry.begin(), *this, begin() );
		int i = 0;
		//就像二进制进位,一直进到遇到0的时候才停下来(对应这里的空列表)
		//或者是超出原先的最高位了,这时候i==fill,所以后面的fill就要加1了
		while( i<fill && !counter[i].empty() ){
			counter[i].merge(carry);
			carry.swap(counter[i++]);
		}//只有在这个while中才有可能出现counter[i]的元素个数大于i^2
		carry.swap( counter[i] );
		if( i==fill ) ++fill;
	}

	for( int i=1; i<fill; ++i )
		counter[i].merge(counter[i-1]);
	swap(counter[fill-1]);
}

list的整个过程就像我们对一个二进制x从0开始一步一步地加1,一开始x=0,第0位都是为空,所以counter[0]为空,fill为0,意思是说所有的counter[i]都为空。carry是中转站,代表一个1,但是它是第几位的,由i来标识。加入一个元素相当于一个加1操作,0+1=1,加完后counter[0]有一个元素,fill=1,没有进位,现在最高位在0位上。然后又加入一个元素,结果产生了进位,于是由carry来管理,现在i=1,所以应该把它加在counter[1]上,此时counter[1]为空(相当于为0),所以没有进位。整个过程就是这样,相当的过程就是一个mergesort的过程。不知道我讲明白了没。。

另一个比较有意思的是stl的power,例如我们现在要算x^7,其可以转换成下面的计算过程:
x^7 = (x^6)*x = ((x^3)^2)*x = (((x^2)*x)^2)*x
本来如果一个x一个x地去乘的话,需要乘以7次,转换成上面的算法,就只需要进行4次乘法。复杂度由O(n)降为O(lgn)。

template<class T>
T power( T x, int n ){
	if( n == 0 )
		return 1;
	while( (n&1) == 0 ){
		x = x*x;
		n >>= 1;
	}//把x^n转换成x^t的平方的平方的平方,直到n为0或n为奇数

	T result = x;		//现在,result=x^t,且n为奇数
	n >>= 1;
	while( n != 0 ){
		x = x*x;
		if( (n&1) != 0 )
			result *= x;
		n >>= 1;
	}
	return result;
}


我们都知道qsort是怎么回事,找一个pivot,以它为中值进行分区,以这个pivot为中界,一前一后,然后再对两个分区进行同样的操作,分而治之地将数组进行排序。理想情况下,算法的复杂度为O(lg(n)),可是不理想的情况下,理论上是O(n^2),但是比起那些本来就是O(n^2)的排序算法要糟糕得多,因为它用的是递归。影响qsort性能的主要可以由下面几点来概括:
(1)pivot的选择,如果pivot不幸正好选到的是数组中最大的或最小的值,那么将形成一个空分区和一个n-1的分区,也就是说,整个过程就是找出了一个最大或最小值;因此在stl的内省快排introsort中,它用一个median_of_three来选择pivot,至少排除了空分区的情况;
(2)但是极端的说,可能会得到一个只有一个元素的分区和一个有n-2个幸免于难的分区,也就是分区效果还是不好,当检测到分割恶化时(因为比较好的情况下是递归了logn次,所以可以通过递归的深度来检测是否出现分区恶化的情况),转而使用heapsort,其实heapsort的复杂度也是O(logn)。
(3)对于大数组,递归的性价比比较高可是对于小数组还进行递归,性价比可能还不如那些复杂度为O(n^2)的非递归的什么insertsort之类的,所以当数组的长度低于某个阈值时,不再递归下去。由于通过qsort后数据的分布已经很好了,所以可以再用一个finnal_insertion_sort对其进行一次整合。这就是sgi stl中的introsort的故事,总的来说,它利用了median_of_three,heapsort和insertion_sort来优化qsort。我就不列出代码了。

这是stl中我印象比较深刻的几个算法。前几天去腾讯面试的时候,面试官问我,你看完stl源码后,印象最深刻的是什么?我当时脑子里就想起这几个算法来,当然,还有它的内存管理,以及利用萃取机制,为了效率,stl大师们真是无所不用其极啊。
分享到:
评论

相关推荐

    谷歌高畅Leetcode刷题笔记.pdf

    作者在美国卡内基梅隆大学攻读硕士期间,为了准备实习秋招,从夏天开始整理LeetCode题目,并在几个月的练习中累积整理了几百道题。因此,本书的编写是建立在作者的刷题经验和项目实践基础之上的。 书籍内容被组织成...

    DEV_C++项目:原神[对话式] Beta V 0.0.6.0 2022-06-01 04:00

    在使用DEV_C++进行项目开发时,开发者通常会涉及以下几个关键知识点: 1. **C++编程语言**:C++是一种强大的、面向对象的编程语言,适用于开发高性能的应用程序。在这个项目中,开发者可能使用了C++的类、对象、...

    C++PPT版的文件

    C++的基础知识主要包括以下几个方面: 1. **基本语法**:C++继承了C语言的基本语法,包括变量声明、类型转换、控制结构(如if-else、for、while循环)、函数定义和调用等。学习者需要掌握这些基本元素,以便编写...

    TinyPathTracing:微小的路径追踪

    在C++中优化路径追踪算法通常涉及以下几个方面: 1. **并行化**:通过多线程或GPU计算来分散负载,利用所有可用的处理器核心。 2. **内存管理**:优化数据结构和内存布局,减少不必要的内存拷贝和访问。 3. **早期...

    vc++ 应用源码包_6

    演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端...

    vc++ 应用源码包_5

    演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端...

    vc++ 应用源码包_1

    演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端...

    vc++ 应用源码包_2

    演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端...

    vc++ 应用源码包_3

    演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology文档。 P2P视频技术源码(含开发文档) PcShare 内含远程控制、进程管理、文件操作、视频控制、注册表操作、客户端...

    vc++ 开发实例源码包

    演示了OpenG的使用方法,内含几个实例,一个实例就3个文件。 p2p vb实例。 p2p+technology 文档。 P2P视频技术源码(含开发文档) 目前的协议有如下一些特点: 1) 客户向服务器发送请求, 每个请求的长度不定. 请求...

    strategy-game-opengl:一个使用OpenGL的策略游戏

    在压缩包“strategy-game-opengl-master”中,我们可以预期包含以下几个关键部分: 1. 源代码文件:这些文件通常以.cpp和.h为扩展名,包含了游戏的各个模块,如游戏逻辑、图形渲染、网络通信、AI算法等。 2. 资源...

Global site tag (gtag.js) - Google Analytics