过程记录

4个月前C语言版的七大排序算法实践让我在写C++版时轻车熟路。特别是冒泡,插入,希尔,选择这四种排序不用调试即运行成功。
输出的效果与C语言做的版本完全一样,其中令我印象深刻的是,cout对浮点的处理远不如printf简单明了。非常让开发者难受。

写C++版时有所改进。

#define sortfunc _selsort

可以用

typedef void (*sort_t)(vector<int>& arr);
sort_t sortfunc = _selsort;

两句代替。
也缩短了把函数指针作参数书写的长度。

很奇怪,又发现C语言版的堆排序是有问题的。
这次先把C++版堆写对了再回头写C语言版。写完后对堆理解加深不少。

堆具有几点性质:

1、任意arr[i/2]<= arr[i]。
2、堆顶元素最小。
3、堆对应数组下标为1..n。
4、最坏插入删除一个元素只需log2n,构造堆最坏nlog2n时间,但是处理平常输入的数据通常不如快速排序。

堆排序算法:

1、待排序目标是arr[1]到arr[n]
2、造堆
    a)前n-1号已经满足堆性质。增加一个n号,移动n号造堆,使得前n号为止都满足堆。
    b)考虑n/2,n(如果n是奇数则考虑n/2,n,n-1),交换n与n/2或交换n-1与n/2,使得n/2最小。(注:n/2总是整数)
    c)若b)没交换,到d);若b)发生交换,使n=n/2,重复b)操作。
    d)前n号满足堆,使n=n+1,重复a)操作直到成功。
3、尖堆
    a)1到n号具有堆性质,所以1号最小,交换1和n号并移动1号使1到n-1号重新恢复堆。
    b)j=1,考虑j,j*2,j*2+1,交换j与j*2或交换j与j*2+1使得j最小。
    c)若b)没交换,到d);若b发生交换,j=j*2(或j*2+1,看交换的是哪个),重复b)。
    d)1到n-1号具有堆性质,使n=n-1,重复a)。
4、反序
5、arr[1]到arr[n]已排序
(以上算法描述个人原创,代码虽易,描述不易,且描且珍惜……)

C++的(vector)版

void _hsort(vector<int>& arr, int len){
// vector<int> arrtmp (len+1);
arr.resize(len+1);
int i,j,k;
// 右移一位
for (i=len;i>=1;i--) // bug! i>1
arr[i] = arr[i-1];
// 造堆
for (i=2;i<=len;i++){
/* 这种就是用while比for好
for (j=i/2;j>1 && arr[j]<arr[j/2];j/=2)
swap(arr[j], arr[j/2]);
*/
j = i;
while (j>1){
k = j/2;
if (j%2 && arr[j-1]<arr[j])
j -= 1;
if (arr[j]<arr[k])
swap(arr[j], arr[k]);
j = k;
}
}
// 交换头尾,恢复推性质,直至反序排列
for (i=len;i>1;i--){
swap(arr[1], arr[i]); //bug! 现在只要回复1到i-1的堆性质,而不是到i
j = 1;
while (j<i-1) {
k = j*2;
if (k>i-1)
break;
// 小的先上,冒泡味道
if (k+1 <=i-1 && arr[k] > arr[k+1])
k += 1;
if (arr[j]>arr[k])
swap(arr[j], arr[k]);
j = k;
}
}
// 反序
i=1;j=len;
while (i < j){
swap(arr[i], arr[j]);
i++;j--;
}
// 复位
for (i=0;i<len;i++)
arr[i] = arr[i+1];
arr.resize(len);
}

C语言版

void _hsort(int arr[], int len)
{
int i,j,t;
/*int *arrtmp = (int*)malloc((len+1)*sizeof(int));
for (i=0; i<len; i++)
arrtmp[i+1] = arr[i];*/
int *arrtmp = arr-1; /*处理技巧:这样就不用额外内存,注意不要用arrtmp[0];*/
/* make heap */
for (i=2; i<=len; i++){
/* shift up 以保持堆性质 */
j=i,t=j/2;
while (t>=1){
if (j%2 && arrtmp[j]>arrtmp[j-1])
j -= 1;
if (arrtmp[t]>arrtmp[j])
swap(arrtmp[t], arrtmp[j]);
j=t,t=j/2;
}
/*t = i/2;
*while (t>=1 && arrtmp[t]>arrtmp[i]){
* swap(arrtmp[t],arrtmp[i]);
* i = t, t = i/2;
*}
* Bug!
* while循环见鬼了:
* 1、去掉swap句会死循环,2、平方时间。
* gdb display t 跟踪,t值变化很吓人。
* 找3小时同时gdb display i才找到原因:i=t,t=i/2;改变了外层for的i递增。相当隐秘。
*/
}
/* 排序后是逆序的 */
for (i=len; i>=2; i--){
swap(arrtmp[i], arrtmp[1]);
/* shif down */
j = 1, t = j*2;
while(t<i-1){
if (t+1<i && arrtmp[t]>arrtmp[t+1])
t += 1;
if (arrtmp[t] < arrtmp[j])
swap(arrtmp[t], arrtmp[j]);
j = t, t = 2*j;
}
}
i=1,j=len;
while (i<j)
{
swap(arrtmp[i], arrtmp[j]);
i++; j--;
} /* bug!! arrtmp[i++] = arrtmp[j--]; */
/*for (i=0; i<len; i++)
arr[i] = arrtmp[len-i];
free(arrtmp);*/
}

技巧

一、传入的数组指针有效下标一般是0到n-1,而堆排序要求下标是1到n。
    解决方法:新建指针变量指向传入指针的前一个位置,操作新指针即可。
    原来的方法:申请内存,错位复制过去,排序后复制回来。

git记录

发现_hsort函数问题

从master的某个提交checkout,然后git branch 建立分支, 再checkout到分支

在分支上修复成功后git rebase都几个分支上,出现冲突,解决,继续,因为冲突,git log显示之前的提交时间都被修改了。

所以应该用git merge比较好。

 

【实习记】2014-08-27堆排序理解总结+使用typedef指代函数指针的更多相关文章

  1. 实习记——《Rethink》

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/gmszone/article/details/30045055 最终能够在和自己的电脑上写下这些字了 ...

  2. 2017年1月1日 星期日 --出埃及记 Exodus 21:27

    2017年1月1日 星期日 --出埃及记 Exodus 21:27 And if he knocks out the tooth of a manservant or maidservant, he ...

  3. 2016年10月16日 星期日 --出埃及记 Exodus 18:27

    2016年10月16日 星期日 --出埃及记 Exodus 18:27 Then Moses sent his father-in-law on his way, and Jethro returne ...

  4. 2016年6月30日 星期四 --出埃及记 Exodus 14:27

    2016年6月30日 星期四 --出埃及记 Exodus 14:27 Moses stretched out his hand over the sea, and at daybreak the se ...

  5. 【实习记】2014-09-26恢复linux下误删的ntfs盘中的文件

        情景,ubuntu下把NTFS格式的盘中的“实习记”文件夹彻底删除了,追毁莫及,粗心觉不是一件好的事情. linux下回复ntfs盘下的文件不能用ext3grep,而使用debugfs命令实在 ...

  6. js 时间 Fri Dec 12 2014 08:00:00 GMT+0800

    第一种var d = new Date('Fri Dec 12 2014 08:00:00 GMT+0800'); ) + '-' + d.getDate() + ' ' + d.getHours() ...

  7. Image Processing and Computer Vision_Review:A survey of recent advances in visual feature detection(Author's Accepted Manuscript)——2014.08

    翻译 一项关于视觉特征检测的最新进展概述(作者已被接受的手稿) 和A survey of recent advances in visual feature detection——2014.08内容相 ...

  8. HGE引擎改进——2014/2/18 和 2014/2/27

    2014/2/18 更新 hgehelper库:增加hgeSkeleton类,该类用于播放骨骼动画 增加工具骨骼动画编辑器(AnimationEd),该工具用于骨骼动画的编辑 2014/2/27 更新 ...

  9. HGE引擎改进——2014/1/27

    2014/1/27 更新 hge库: 1.增加回调函数procResizeFunc(),这个函数会在窗口大小改变时调用,不是必要函数 2.修复LOG信息显示为乱码的错误 项目主页:https://co ...

随机推荐

  1. 如何将可执行文件打包至APK并运行(转)

    原文链接:http://www.lupaworld.com/home.php?mod=space&uid=345712&do=blog&id=248921 好久没有写bolg了 ...

  2. 问题-delphi XE2 Stack Overflow- save your work and restart CodeGear

    问题现象:某一天,启动DLEPHI XE2 后,新建一个工程,双击一个事件,“Stack Overflow- save your work and restart CodeGear delphi xe ...

  3. 问题.NET访问 IIS 元数据库失败。

    问题现象:访问 IIS 元数据库失败. 说明:执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细信息: System.We ...

  4. 导入excel数据

    前提条件:先要安装好EXCEL软件. 程序中经常要用到导入excel数据的功能.其实通过ole操作excel就简单的几行代码,但记性不好,经常要用经常要找, 还是作篇笔记吧. var ExcelApp ...

  5. oracle 表空管理方式(LMT)、ASSM段管理方式、一级位图块、二级位图块、三级位图块。

    今天是2013-12-16,今天和明天是我学习oracle生涯中一个特殊的日子.今天晚上进行了一下表空间管理方式的学习,在此记录一下笔记. 对于oracle数据库最小i/0单位是数据块,最想分配空间单 ...

  6. SGU107——987654321 problem

    For given number N you must output amount of N-digit numbers, such, that last digits of their square ...

  7. 四、XML映射配置文件

    MyBatis的XML配置文件包含了影响MyBatis行为甚深的设置和属性信息.XML文档的高层级结构如下: ----configuration配置 --------properties属性 ---- ...

  8. 24C02操作--松瀚汇编源码

    ; ; P_CLKIIC EQU P1.2 ; P_DATIIC EQU P1.3 ; PM_DATIIC EQU P1M.3 ; EE_ADDR DS 1 ;地址寄存器 ; TMP3_IIC DS ...

  9. AptanaStudio3 安装在win7 64bit时遇到的问题

    最近在研究前端语言,想起可以使用AptanaStudio这个前端利器,没想到安装时却遇到波折.先从网上下载了Aptana版本 3.6.0 64bit问题1 安装进度缓慢,第一次安装时,显示downlo ...

  10. hdu 3183 A Magic Lamp(RMQ)

    题目链接:hdu 3183 A Magic Lamp 题目大意:给定一个字符串,然后最多删除K个.使得剩下的组成的数值最小. 解题思路:问题等价与取N-M个数.每次取的时候保证后面能取的个数足够,而且 ...