是否拥有扎实的算法知识和技术基础,是区分真正熟练的程序员与新手的一项重要特征。虽然利用当代的计算技术,无需了解很多算法方面的知识,也可以完成一些任务,但是如果有良好的算法基础和背景的话可以做更多的事情,并且拥有更强的思维能力。学生时期虽然全面学习过算法导论里的相关知识,但是学生时没有太多的编程经验,实践算法时候需要边看书上的伪代码边写程序才能实现,经过工作几年,很多知识已经不记得了。现在想重新拿起,因此将实践过程做些记录方便加深理解与记忆。
插入排序
以我们玩扑克牌时摸牌过程可以非常形象地理解插入排序,我们每从牌堆里摸起一张牌,边从右往左比较每张排的大小,然后将当前的牌插入到第一张比它小的牌后面,这样的排序过程保证手里的牌总是排好序。
下图是书中形象地介绍插入排序实现过程:
插入排序过程从第2个数开始遍历输入数组,图中深黑色部分为每趟排序过程的“当前牌”,将“当前牌”逐个与前面灰色元素的数值比较,如果该数值比“当前牌大”,则将该元素往后移动一个位置,直到找到第一个比“当前牌”小的元素,然后将“当前牌”插入到该元素的后面。
插入排序C++实现:
插入排序最坏情况是输入数据为逆序的时候,这时候每趟排序,“当前牌”都需要与前面所有的元素进行比较,时间复杂度为:
我实践中对100万个逆序的输入数据进行排序,需要时间为1143.4秒
#include <sys/time.h>
#include <iostream>
#include <fstream>
void InsertionSort(double* data, const int len)
{
assert( data != NULL );
double key = 0.0;
for( int j = 1; j < len; ++j)
{
key = data[ j ];
int i = j - 1;
while ( (i >= 0) && ( data [ i ] > key ) )
{
data[ i + 1 ] = data[ i ];
--i;
}
data[ i + 1 ] = key;
}
}
int main()
{
int len = 1000000;
double* data = new double[ len ];
for( int i = len, j = 0; i > 0 && j < len; --i, ++j){
data[ j ] = i;
}
struct timeval time_start, time_end;
gettimeofday(&time_start, NULL);
//1000000 Time : 1143.4 (s)
InsertionSort( data , len);
gettimeofday(&time_end, NULL);
double time = 1000000 *(time_end.tv_sec -time_start.tv_sec) +
(time_end.tv_usec -time_start.tv_usec);
time /= 1000000;
std::cout<<"Time : "<<time<<" (s) "<<std::endl;
delete []data;
return 0;
}