插入排序:表折半插入
2017-06-26 14:09
211 查看
在前一篇插入排序:表插入中。我们用静态链表的存储方式。直接插入的策略,构建了一种新的插入排序算法:表插入。
有人可能会想到:相同是静态链表的形式,为什么不使用更高效的折半插入策略呢?这样的想法真的非常好,假设做到了。显然是极大的优化。
我在网上还真看到了相关的内容,大家可搜下《表插入方法的改进》,里面有此想法的介绍。这篇博客就是介绍表插入的还有一种实现:表折半插入。看完一定让你彻底理解它!
与一般的折半插入相比,有例如以下的几点变化:
为了实现折半查找,我们对静态链表的节点类型做了一些变化:加入了一个前驱指针。
它的意义非常显然,曾经是high=mid-1,在单向链表中我们是做不到的(事实上能够换种方式做到,只是相对麻烦),于是加入一指向其前驱的指针。构成双向链表,方便进行此操作。
while循环的结束条件,有所不同。这个要细致理解!
其它细节,代码中有详解
细致看完代码,我想大多数人仅仅剩一个问题可能没明确,那就是while循环的结束条件为什么还得加上low!=0 和high!=0?
为了解释清楚。我们画一个图,图中正在插入i=2的节点:
初始化后。low,mid,high显然都指向1,经过下一步rec[i].data与rec[mid].data比較后,不管结果如何,循环都应结束。
可假设rec[i].data<rec[mid].data,就有high=rec[mid].pre,即high=1.此时显然有rec[low]<rec[high],也就是说循环还得接着经进行下去。问题就出在这里!讲到这里,你应该明确:即使出现low为0,它也会违反第三条件:rec[low].data<=rec[high].data)(由于rec[0]的值域是最大的)。这就是为什么说,第一个条件low!=0能够去掉。
到此。你应该明确了代码中全部的凝视。
測试走起啊……
p.s 对rec数组1-n号元素进行重排也是能够的,做法參照上一篇博客哦,方法一模一样。
转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/28635157
若是写得好。顶一个哦。
代码就是折腾,越折腾越进步!
专栏文件夹看这里:
数据结构与算法文件夹
c指针
有人可能会想到:相同是静态链表的形式,为什么不使用更高效的折半插入策略呢?这样的想法真的非常好,假设做到了。显然是极大的优化。
我在网上还真看到了相关的内容,大家可搜下《表插入方法的改进》,里面有此想法的介绍。这篇博客就是介绍表插入的还有一种实现:表折半插入。看完一定让你彻底理解它!
与一般的折半插入相比,有例如以下的几点变化:
为了实现折半查找,我们对静态链表的节点类型做了一些变化:加入了一个前驱指针。
它的意义非常显然,曾经是high=mid-1,在单向链表中我们是做不到的(事实上能够换种方式做到,只是相对麻烦),于是加入一指向其前驱的指针。构成双向链表,方便进行此操作。
while循环的结束条件,有所不同。这个要细致理解!
其它细节,代码中有详解
const int MAX=100; typedef struct rec { int data; int pre; //前驱 int next; //后继 }Rec; void InsertSort(int a[], int n) //表折半插入 { Rec *rec=new Rec[n+1]; for(int i=0; i<n; i++) { rec[i+1].data=a[i]; rec[i+1].next=rec[i+1].pre=0; } rec[0].data=MAX; rec[0].next=rec[0].pre=1; int low,high,mid; int p,k,l; for(int i=2; i<n+1; i++) { //依据下面的赋值,我们能够看出。这里使用的是左闭右闭区间 low=rec[0].next; //low指向最小的 high=rec[0].pre; //high指向最大的 l=i-1; //已有序的元素个数 while(low!=0 && high!=0 && rec[low].data<=rec[high].data) //循环结束条件得理解,特别是前两个条件。 准确的是。第一个条件能够不要 { mid=low; k=1; l/=2; // l>>=2 减半。为下次循环做好准备 while(k<l) //寻找mid位置 { mid=rec[mid].next; k++; } if(rec[i].data<rec[mid].data) high=rec[mid].pre; else low=rec[mid].next; } //插入第i个节点。相似于双向链表的插入 rec[rec[low].pre].next=i; rec[i].pre=rec[low].pre; //加入前驱指针的作用体如今这里 rec[i].next=low; rec[low].pre=i; } //顺着next指针方向打印 printf("表折半插入排序后\n"); p=rec[0].next; while(p!=0) { printf("%-4d",rec[p].data); p=rec[p].next; } printf("\n"); }
细致看完代码,我想大多数人仅仅剩一个问题可能没明确,那就是while循环的结束条件为什么还得加上low!=0 和high!=0?
为了解释清楚。我们画一个图,图中正在插入i=2的节点:
初始化后。low,mid,high显然都指向1,经过下一步rec[i].data与rec[mid].data比較后,不管结果如何,循环都应结束。
可假设rec[i].data<rec[mid].data,就有high=rec[mid].pre,即high=1.此时显然有rec[low]<rec[high],也就是说循环还得接着经进行下去。问题就出在这里!讲到这里,你应该明确:即使出现low为0,它也会违反第三条件:rec[low].data<=rec[high].data)(由于rec[0]的值域是最大的)。这就是为什么说,第一个条件low!=0能够去掉。
到此。你应该明确了代码中全部的凝视。
測试走起啊……
p.s 对rec数组1-n号元素进行重排也是能够的,做法參照上一篇博客哦,方法一模一样。
转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/28635157
若是写得好。顶一个哦。
代码就是折腾,越折腾越进步!
专栏文件夹看这里:
数据结构与算法文件夹
c指针
相关文章推荐
- 插入排序--折半插入
- Java四种排序:冒泡,选择,插入,二分(折半插入)
- 插入排序之折半排序Java实现
- 插入排序:表折半插入
- 插入排序--折半插入
- C语言基本数据结构之五(折半插入,堆排序,冒泡排序,快速排序,并归排序)
- 插入排序:直接插入, 折半插入,希尔插入
- 排序算法--插入排序(直接插入排序、折半插入、shell排序)的java实现
- 8.1 内部排序法---插入类排序(直接插入、折半、希尔)
- 插入类排序--直接插入、折半插入、希尔
- 折半(二分)插入排序
- 排序大全【各种排序】:直接插入,折半插入,冒泡,快排,简单选择,堆排序,归并排序
- 七种排序(直接插入、折半插入、希尔、起泡、快速、简单选择、堆排序)
- 冒泡,插入,折半插入,希尔,快速,简单选择排序的源代码总结
- (1.3.3)插入排序:直接插入、交换插入、折半插入
- c语言排序实例(选择、冒泡、插入、折半、快速)
- 直接插入排序和折半插入实现
- 七种排序(直接插入、折半插入、希尔、起泡、快速、简单选择、堆排序)
- C语言排序实例(选择、冒泡、插入、折半、快速)
- C语言排序实例(选择、冒泡、插入、折半、快速)