大家好,我是一只学弱狗,记录学习的点点滴滴!
算法才是程序设计的灵魂,每日一题!
优质文章
优质专栏
今天看算法很美的时候呢,老师提到了希尔排序,以前听说过希尔排序,但是在我写这篇博客的前一个小时,我是真的忘记了,还记得大一那会,分不清希尔与哈希,呜呜~,不愧是我,现在就来说说希尔排序,希望对你有所收获哦!
讲希尔排序之前,我想先跟大家讲下插入排序,因为希尔排序的本质的插入排序,讲插入排序之前呢,我想先问大大伙一个问题,你递归学的怎么样?
毛啊,扯哪了,先别急,其实我看希尔排序的起因是在看插入排序,跟准确一点的话应该是使用递归方式的写的插入排序,如果你会递归的话,何不停下来,举一反三,自己写一个用递归方式实现的插入排序,再此体会下递归呢?
插入排序的思想,对于第i个元素而言,假设前i-1个元素已经是排序好的了(这里假设从小到大排序),那个这时只需将第i个元素与它的前一个元素i-1比,如果大于前一个元素,则无需任何元素的移动,如果小于,则前一个元素向后挪动一个位置,第i个元素,在与它的前两个元素i-2比,依次反复的执行即可。
下面写下代码
递归实现
//从小到大
void sort(int array[],int k){
//递归的结束条件,一般我都喜欢最后写,即先把主要逻辑写出来
if(k==1) return ;
//对array的前k-1个元素进行排序
//重复子问题
sort(array,k-1);
int i;
//取出数组的最后一个值
int value = array[k-1];
int index = k-2;
//这儿用while更好些
while(array[index]>value && index>-1){
array[index+1]=array[index];
index--;
}
array[index+1] = value;
}
循环
//incre为增量 现在你把它都做1就好
void insert_sort(int array[],int size,int incre){
for(int i=incre;i<size;i++){
int tmp = array[i];
int j=i-incre;
while(array[j]>tmp && j>-1){
array[j+incre] = array[j];
j-=incre;
}
array[j+incre]=tmp;
}
}
插入排序聊完后,进入今天的主题,即希尔排序,那希尔排序是什么呢?首先你得知道它是插入排序的改进,插入排序我们其实可以看做是增量为1的希尔排序,即一个元素,都是先和它的前一个元素进行比较,若满足条件,再与前两个元素进行比较,增量为1,而希尔排序呢,则是与前x个元素进行比较,画个图了解下
增量的选取也是有讲究的,它关系到算法的快慢,作为练习,我们每次取数组长度的一半就行,比如数组长度为8,则序列为{4,2,1},所以增量序列也得遍历,从粗粒度的4到细粒度的1
实现代码如下
void shell_sort(int array[],int size){
int seq = size;
//得到增量序列
vector<int> increSequence;
while(seq>1){
increSequence.push_back(seq>>=1);
}
//插入排序
for(int i=0;i<increSequence.size();i++){
insert_sort(array,size,increSequence[i]);
}
}
void insert_sort(int array[],int size,int incre){
for(int i=incre;i<size;i++){
int tmp = array[i];
int j=i-incre;
while(array[j]>tmp && j>-1){
array[j+incre] = array[j];
j-=incre;
}
array[j+incre]=tmp;
}
}
我们输入一个序列测试下,希尔排序与插入排序的快慢,对如下挪动操作进行计数
while(array[j]>tmp && j>-1){
ans++;
array[j+incre] = array[j];
j-=incre;
}
加入数组为{9,8,7,6,5,4,3,2,1},
使用插入排序,运行结果如下图
使用希尔排序,运行结果如下图
这块了高几倍了,当前,谁快谁慢根据业务需求而定,我们重要的是理解这种思想,这才是真正程序的灵魂,好了,今天就跟大家聊到这里了!