【算法】插入排序 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)
插入排序对于少量元素的排序是很高效的,而且这个排序的手法在每个人生活中也是有的哦. 你可能没有意识到,当你打牌的时候,就是用的插入排序. 概念 从桌上的牌堆摸牌,牌堆内是杂乱无序的,但是我们摸上牌的时 ...
随机推荐
- intel线程库tbb的使用
[size=small]首先下载: http://www.threadingbuildingblocks.org/uploads/77/111/2.1/tbb21_20080605oss_win.zi ...
- 多路复用I/O select()
select(),poll(),epoll()的总结:http://www.cnblogs.com/Anker/p/3265058.html 在socket编程中,仅仅使用connect,accept ...
- 如何把一个表中的部分字段值插入到另一个表中去 这sql吊
Insert into JHAC_TB_CODE(CID,CODE,ADD_TIME,USERID,PRO_CODE,USERNAME) select f_code.FID,f_code.Fcod ...
- mongodb数据文件内部结构
有人在Quora上提问:MongoDB数据文件内部的组织结构是什么样的.随后10gen的工程师Jared Rosoff出来做了简短的回答. 每一个数据库都有自己独立的文件.如果你开启了director ...
- Stack Overflow 上排名前十的与API相关的问题
Stack Overflow是一个庞大的编程知识仓库,在Stack Overflow 上,数百万的提问被回答,并且这些回答都是高质量的.这就是为什么在Google搜索结果的排行榜上,Stack Ove ...
- sqlite编译
1.下载代码:http://www.sqlite.org/download.html ,windows下下载sqlite-amalgamation-xxx.zip和sqlite-dll-win32-x ...
- 自定义ListView分割线
要完成自定义分割线,我们先来认识一下listview中的两个属性: android:divider 设置list 列表项的分隔条(可用颜色分隔,也可用Drawable分隔) android:divid ...
- 类XX是公共的,应在名为XX.java的文件中声明public class XX
找了一个程序粘贴到txt文档中,随便起个名为abc,然后改后缀为.java,接下来在dos中运行时出现以上错误 打开abc.java看了看,声明public class了,但是名字是粘贴过来的类名Wo ...
- cf C. Cupboard and Balloons
http://codeforces.com/contest/342/problem/C #include <cstdio> #include <cstring> #includ ...
- Eclipse标准版安装J2EE
虽然有Eclipse IDE for Java EE Developers,已经包含了j2ee的插件,但有时我们需要在标准版上安装插件来达到开发j2ee的功能. 安装 Java EE 插件: * 依 ...