【算法】插入排序 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)
插入排序对于少量元素的排序是很高效的,而且这个排序的手法在每个人生活中也是有的哦. 你可能没有意识到,当你打牌的时候,就是用的插入排序. 概念 从桌上的牌堆摸牌,牌堆内是杂乱无序的,但是我们摸上牌的时 ...
随机推荐
- Android 自定义UI--指南针
有了之前的基础,下面开始实现一个简单的指南针.首先来看一下效果图, 我们可以粗略将这个指南针分为三个部分,一是圆形背景,二是刻度,三是文本.那么在写代码的时候,就可以声明三个Paint画笔来画以上三个 ...
- 用sp_change_users_login消除Sql Server的孤立用户
异常详细信息: System.Data.SqlClient.SqlException: 拒绝了对对象 'zwj_EnterpriseActivities' (数据库 'Ntours',架构 'dbo' ...
- 你使用PetaPoco必须知道的事情
之前没有用PetaPoco调用过存储过程,今天发现问题 Sql sql = ); var list = sqlserverDB.GetInstance().Fetch<AdminGroup> ...
- visifire 图表双坐标轴 silverlight
public void CreateChart(Grid oGrid, ObservableCollection<ListItem> lBaseOilBar) { ...
- 定义了重复的system.web.extensions/scripting/scriptResourceHandler怎么办
今天移转系统,都配置好之后,系统报错说我的web服务下的web.config 定义了重复的 system.web.extensions/scripting/scriptResourceHandler ...
- (原+转)ubuntu终端输出彩色文字
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6066697.html 参考网址: http://www.tuicool.com/articles/jI ...
- ORA-01722: invalid number,ORA-12801
SQL: SELECT /*+ parallel(a,32) */ a.id ,a.data_date ,a.mobile_num ,a.mobile_code ,b.prov AS mobile_p ...
- php+mysql将大数据sql文件导入数据库
<?php $file_name = "d:test.sql"; $dbhost = "localhost"; $dbuser = "root& ...
- 【JAVA编码专题】JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考. 为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问 ...
- js中constructor的作用
在学习过程中对js的constructor的作用产生了疑问.下面是学习的资料进行梳理 function Person(area){ this.type = 'person'; this.area = ...