【算法】插入排序 insertion_sort
准备写个《STL 源代码剖析》的读书笔记,开个专栏。名为《STL 的实现》,将源代码整理一遍。非常喜欢侯捷先生写在封底的八个字:天下大事。必作于细。他在书中写到:“我开玩笑地对朋友说,这本书出版,给大学课程中的「数据结构」和「算法」两门授课老师出了个难题。差点儿全部可能的作业题目(复杂度证明题除外),本书都有了详尽的解答。
然而,假设学生可以从庞大的SGI STL源代码中干净抽出某一部份,加上自己的包装,做为呈堂作业,也足以证明你有资格获得学分和高分。其实。追踪一流作品并于当中吸取养份,远比自己关起门来写个三流作品,价值高得多—我的确觉得99.99%的程序猿所写的程序,在SGI
STL面前都是三流水平。
”有的人说仅仅需把 STL 的那些接口弄清楚即可了。没有必要看它是怎样实现的,我觉得你要是不看的话真的太可惜了,而侯先生则觉得“从技术研究与本质提升的角度看。深究细节能够让你彻底掌握一切;不论是为了重温数据结构和算法,或是想要扮演轮子角色。或是想要进一步扩张别人的轮子,都可因此获得深厚扎实的基础。
”
本专栏分为【容器】、【算法】、【迭代器】、【分配器】、【适配器】、【仿函数】等几个部分。第一篇解说 STL 内置的一个算法:插入排序,它将用于 std::sort 中。
普通的插入排序算法例如以下:
typedef int Type; // 程序中用到的 Type 都是由 traits 得来,这里简化了 template <class RandomAccessIterator>
void insertion_sort(RandomAccessIterator first, RandomAccessIterator last) {
if (first == last) {
return ;
} RandomAccessIterator p;
for (RandomAccessIterator ite = first + 1; ite != last; ++ite) {
Type tmp = *ite;
for (p = ite; p != first && tmp < *(p - 1); --p) {
*p = *(p - 1);
}
*p = tmp;
}
}
当中内循环的终止条件中有一关系表达式 p != first 用于推断是否越界。而在 STL 的实现中为了减小这一开销,在以下的 linear_insert 函数的開始就检測尾是否小于头,若不成立,就表明要插入的元素一定不会排在最前面,所以在后面的移动元素过程中就不用作越界检查了,它的作用类似于“哨兵”。STL 中插入排序的实现例如以下:
/********************************************************************
created: 2014/04/21 22:03
filename: insertion_sort.cpp
author: Justme0 (http://blog.csdn.net/justme0) purpose: insertion sort
*********************************************************************/ #include <cstdio>
#include <cstdlib>
#include <cstring> typedef int Type; // 程序中用到的 Type 都是由 traits 得来。这里简化了 /*
** 将[first, last)拷到[result-(last-first), result)。从后向前复制
** 这里简化了 std::copy_backward
*/
template <class T>
inline T * copy_backward(const T *first, const T *last, T *result) {
const ptrdiff_t num = last - first;
memmove(result - num, first, sizeof(T) * num);
return result - num;
} /*
** 将 value 插到 last 前面(不包含 last)的区间
** 此函数保证不会越界(主调函数已推断),因此以 unguarded_ 开头
*/
template <class RandomAccessIterator, class T>
void unguarded_linear_insert(RandomAccessIterator last, T value) {
RandomAccessIterator next = last;
--next;
for (; value < *next; --next) {
*last = *next;
last = next;
}
*last = value;
} /*
** 将 last 处的元素插到[first, last)的有序区间
*/
template <class RandomAccessIterator>
void linear_insert(RandomAccessIterator first, RandomAccessIterator last) {
Type value = *last;
if (value < *first) { // 若尾比头小,就将整个区间一次性向后移动一个位置
copy_backward(first, last, last + 1);
*first = value;
} else {
unguarded_linear_insert(last, value);
}
} template <class RandomAccessIterator>
void insertion_sort(RandomAccessIterator first, RandomAccessIterator last) {
if (first == last) {
return ;
} for (RandomAccessIterator ite = first + 1; ite != last; ++ite) {
linear_insert(first, ite);
}
} int main(void) {
Type arr[] = {3, 1, 5, 2, 0, 4};
int size = sizeof arr / sizeof *arr; insertion_sort(arr, arr + size); for (Type *ite = arr; ite != arr + size; ++ite) {
printf("%d ", *ite); // 0 1 2 3 4 5
} system("PAUSE");
return 0;
}
能够看到,实现中将这个算法多次抽象,这是由于有的函数譬如 unguarded_insertion_sort 将用于其它算法,便于代码重用。
STL 的源代码编写是非常有讲究的,比方上面的 value < *first 这个表达式,可不能写成 *first > value,由于迭代器所指的对象未必然义了大于这个操作,标准中规定要排序。client必须保证小于号的定义(或是传入仿函数作为比較标准)。所以源代码中就仅仅用小于来推断。
【算法】插入排序 insertion_sort的更多相关文章
- 经典排序算法 – 插入排序Insertion sort
经典排序算法 – 插入排序Insertion sort 插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种, ...
- 排序算法--插入排序(Insertion Sort)_C#程序实现
排序算法--插入排序(Insertion Sort)_C#程序实现 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题.例如,字典中的单词是以字母的顺序排列,否则,使用起来 ...
- 数据结构和算法(Golang实现)(21)排序算法-插入排序
插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...
- 使用 js 实现十大排序算法: 插入排序
使用 js 实现十大排序算法: 插入排序 插入排序 // 双重循环 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- Python排序算法——插入排序
有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10787464.html 一.插入排序(Inse ...
- 疯狂的Java算法——插入排序,归并排序以及并行归并排序
从古至今的难题 在IT届有一道百算不厌其烦的题,俗称排序.不管是你参加BAT等高端笔试,亦或是藏匿于街头小巷的草根笔试,都会经常见到这样一道百年难得一解的问题. 今天LZ有幸与各位分享一下算法届的草根 ...
- [算法] 插入排序 Insertion Sort
插入排序(Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in-pla ...
- 插入排序(insertion_sort)
最简单的排序算法,又称插值排序,原理类似于打扑克牌时把摸到的牌插入手中已有序牌的过程. void insertion_sort(int* A ,int n){ int i,j,key; ;i < ...
- 排序算法 - 插入排序(Insertion sort)
插入排序对于少量元素的排序是很高效的,而且这个排序的手法在每个人生活中也是有的哦. 你可能没有意识到,当你打牌的时候,就是用的插入排序. 概念 从桌上的牌堆摸牌,牌堆内是杂乱无序的,但是我们摸上牌的时 ...
随机推荐
- C# 操作 AppSettings节点
1.实例 //1.简单获取内容 string value = ConfigurationManager.AppSettings["one"] as string; Console. ...
- .net安装windows服务配置文件config
.net安装windows服务 : 在windows服务的项目(WindowsService1)代码文件中有一个app.config 配置文件,可以通过此文件进行时间等的更改而无需重新生成项目:那我们 ...
- 解决mdi窗体闪烁的问题
/// 解决mdi窗体闪烁的问题 /// </summary> protected override CreateParams CreateParams { get { CreatePar ...
- 嵌入式开发——boa服务器下的ajax与cgi通信
博主最近在最有做一个嵌入式课程设计,要求是利用基于cortax a8的物联网实验箱做一个简单的嵌入式网页交互系统作为课程设计来验收评分.因为本身自己是学前端的,所以网页部分并不是重点,主要是和boa服 ...
- poj1006 孙子定理
Biorhythms Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 127944 Accepted: 40566 Des ...
- C++11 lambda表达式学习
lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的lambda表达式自己的认识.这里有参考文档h ...
- bootstrap-paginator 分页控件的使用
首先对js和css的引用 <link rel="stylesheet" href="reference/bootstrap/css/bootstrap.min.cs ...
- (原)ubuntu16重装显卡驱动后,torch中的问题
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6030232.html 参考网址: https://github.com/torch/cutorch/i ...
- JQuery实现倒计时效果
首先:引入jquery文件 <script type="text/javascript" src="http://www.cnblogs.com/Content/P ...
- 异常处理:你不可能总是对的 - 零基础入门学习Python032
异常处理:你不可能总是对的 让编程改变世界 Change the world by program 因为我们是人,不是神,所以我们经常会犯错.当然程序员也不例外,就算是经验丰富的码农,也不能保证写出来 ...