1.2排序——选择,希尔:“指针传递”是什么

第一节似乎写的字太多了,这一节让我们直接开始正文。

选择排序

选择排序,算法如其名,就是“选择一个最小(最大)的放到合适的位置”。

所以,让我们大致描述一下算法的流程:

1.从所有位置中选择一个位置,当作要交换的位置。和插入排序有些不同,Insert选择的是要交换的数,而选择则选择的是要被排好的位置。什么意思呢,就是当我们选择位置==0时,我们要的结果是一个放在此位置的数,即最小值或最大值。所以,我们应该选作比较的量,是位置。

2.在内部循环中,我们遍历所有的数,找到最小的,放在此位置。
注意:1)每次都不能选拍好的位置上的数重新比较。
2)最后一个“数”不用比较,其实是前面的位置都排好以后,最后的位置也就固定了。

假设我们要求的是升序序列,则算法如下:

template <typename T>
void SelectSort( T A[ ], int N )
{
    for( i = N - 1; i > 0; --i )
    {
        int tmp = i;  //将第i个位置暂时设为tmp,用做比较
        for( int j = 0; j < i; ++j )
            if( A[ j ] < A[ tmp ])
                tmp = j;
        swap( &A[ i ], &A[ tmp ]);  //最后那个最小的和本次循环的位置(i)进行交换
}

“注意”的第一条反映在代码中就是:for( j = N - 1; j > i; --j)而不是for( j = N - 1; j > 0; --j),为啥不能拿选好的位置重新比较呢?想一想就知道啦,选好的已经是最小的了,你拿这个比,不就是拿最小的去比,相当于把最小的又放到了其他位置说啦。

此处需要有个交换的函数,只要学过大一“c语言程序设计”的同学们,就一定知道,你们的老师肯定在这里说过很多遍,“交换的时候要用指针啦,因为只有指针传递才能真的交换,值传递出了作用域是没用的啦”,那么我们先把使用指针传递的函数写出来吧:

template <typename T>
void swap( T *a, T *b )
{
    auto tmp = *a;
    *a = *b;
    *b = tmp;
}

首先,这代码是正确的;那么,老师说的话是正确的吗?其实,c语言只有值传递,c++只有值传递和引用传递。他们都没有“指针传递”。那么为什么用指针就行了呢,因为我们在做swap()时,具体操作是:swap( &A[ i ], &A[ tmp ]);,也就是说,我们赋给swap()函数的是A[ i ]和A [ tmp ]的地址,swap()接受的也依旧是2个地址的拷贝,我们并没有改变2个地址,改变的是地址指向的对象。更贴近硬件层面的说,通过传递指针的拷贝,我们改变了指针所代表的地址(指针的值就是地址啦~)所指向的值,而这个值则是直接存在于一片内存空间中,于是我们越过了改变地址而直接改变值的内存情况。那么,什么是改变地址呢?

template <typename T>
void swap( *a, *b )
{
    int *tmp = a;
    a = b;
    b = tmp;
}

这就是直接改变地址的写法。很明显,此算法是无效的。把地址当作形参传递后改变地址,最后并不会改变实参中地址的情况。

那么,有没有其他写法呢?当然有,用引用传递。c++中,引用就是变量的别名。在很多语言中,赋值语句已经是默认引用传递了,很多时候为了寻找拷贝,必须得使用一下名为“.copy()”的方法。那么,我们用引用实现一下swap()

template <typename T>
void swap( T &a,  T &b )
{
    auto tmp = a;
    a = b;
    b = tmp;
}

这时,调用swap也相应的变味为了swap(A[i], A[tmp]);,引用传递的好处是不必拷贝,剩下了不少内存~~(同时代码也似乎看得懂了,不是吗!!!)一个需要注意的是,这个时候不要using namespace std;,因为会自动引入系统中的swap,这时编译器就不知道要重载哪个函数了。

希尔排序(shell sort)

话不多说,我们直接看看希尔排序吧。之前我就想把希尔和插入放在一节,因为希尔排序在实现的时候其实就是间隔不同的插入排序。

我们假设间隔取N/2,且每次间隔缩小一半:

template <typename T>
void ShellSort(T A[ ], int N)
{
    int i, j, Increment;  //Increment是增量,就是间隔;i 控制插入排序中的要插入的元素;j控制比较和交换
    T tmp;
    for( Increment = N / 2; Increment > 0; Increment /= 2)
        //下边的就是插入排序,不是吗?
        for( i = Increment; i < N; ++i)
        {
            tmp = A[ i ];
            for( j = i; j >= Increment  && tmp < A[ j - Increment ]; j -= Increment)
                A[ j ] = A[ j - Increment ];
            A[ j ] = tmp;
         }
}

增量不一定要取Increment = Increment / 2,准确地说,不应当取这个,如Hibbard增量:2k-1,k=0...~效果更好。而Sedgewick增量更更好:9*4i-92i+1或者4i-32^i+1。

希尔排序的时间复杂度为亚二次,也就是说,增量选取不同,其从O(N2)到O(N)不等(当然,到不了O(N))。一般的,能达到O(N3/2)。

那么我们下次就聊聊归并排序,以及归并背后的思想和各种时间复杂度证明方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,108评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,706评论 0 15
  • 故事已讲完 人心已散涣 故事的看客永远不会失去什么东西 过了一季的繁华 你也走过了最美的季节 有过信誓旦旦的承诺 ...
    世俗女子阅读 230评论 8 3
  • 美国积极心理学之父马丁•塞利格曼在《活出最乐观的自己》一书中说:“悲观可以帮助我们认清事情的真相”。 昨天在和一位...
    李庆建阅读 391评论 0 1
  • 每个人的生命只有一次,而我,却有两次。 我出生于11月11日,那个时候还没有什么光棍节.双十一。出生后的第七天,我...
    倩儿85阅读 380评论 0 1