前面三种排序算法(冒泡、选择以及插入排序)的时间复杂度都是O( n2 ),相对来说性能最好的是插入排序,在元素个数少,且原序列基本有序的前提下,是非常高效的!所以对于人一个无序序列,我们可以认为的制造上述条件:
- 元素个数少—分组
- 基本有序—按照增量进行分组
这样将相距某个增量的众多元素组成一个子序列,然后在子序列内部分别进行直接插入排序,得到的序列就是所谓的基本有序序列,之后就可以按照增量为1进行插入排序即可完成排序。
希尔排序的时间复杂度突破O( n2 ),是O( n3/2 )。
希尔排序由于使用了跳跃式的比较和交换,是不稳定的排序算法。
关于MarkDown的数学公式参见:
http://www.cnblogs.com/mfrbuaa/p/4882005.html
关于如何选取增量目前没有标准答案,业界使用迭代的方法,求取每次循环的增量,迭代公式是:inc = inc/3 + 1
,inc的初始值是所有元素的个数。
#include <iostream>
using namespace std;
#define MAXSIZE 100
typedef int Status;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
template <typename T>
class SqList
{
public:
T r[MAXSIZE+1];
int length;
public:
SqList(T * var,int len);
SqList();
void printList();
Status swapElement(int i, int j);
void ShellSort();
};
template <typename T>
SqList<T>::SqList(T * var,int len)
{
length = len/sizeof(T);
memcpy(&(r[1]), var, len);
}
template <typename T>
SqList<T>::SqList()
{
memset(this, 0, sizeof(SqList));
}
template <typename T>
Status SqList<T>::swapElement(int i,int j)
{
T tmp =this->r[i];
this->r[i] = this->r[j];
this->r[j] = tmp;
return OK;
}
template <typename T>
void SqList<T>::printList()
{
for (int i = 1; i <= length; i++)
{
cout << this->r[i] << "\t";
}
cout << endl;
}
/************************************************************************/
/* 希尔排序 */
/************************************************************************/
template <typename T>
void SqList<T>::ShellSort()
{
int i, j;
int inc = length;
do //do-while循环主要是用来调节增量
//每调节一次增量代表越来越趋向基本有序
{
inc = inc / 3 + 1;//业界常用迭代公式--增量越来越小,
//每一个分组的元素越来越多
/*分组里面进行插入排序--默认分组的第一个元素已经排好序*/
for (i = inc + 1; i <= length;i++)//i从第inc+1开始(第一个分组的第二个元素)
//然后依次遍历后面的元素,他们相应是每一个分组的第二个元素
{
if (r[i]<r[i-inc])//如果分组的第二个元素比第一个元素小--
//代表需要移动分组里面已经排好序的元素--
//挪出位置以便给当前元素使用
{
r[0] = r[i];//哨兵--缓存当前元素
for (j = i - inc; j > 0 && r[j] > r[0]; j -= inc)//分组里面移动元素--按照增量调节下标
{
r[j + inc] = r[j];//向后移动
}
r[j + inc] = r[0];//在相应位置插入哨兵--完成插入排序
}
}
} while (inc > 1);//增量序列的最后一个增量必须等于1--等于1的时候跳跃式的插入排序--希尔排序完毕
}
int main(void)
{
int myList[9] = {90,10,50,80,30,70,40,60,20};
SqList<int> list(myList,sizeof(myList));
cout << "before sort:"<< endl;
list.printList();
list.ShellSort();
cout << "after sort:" << endl;
list.printList();
cout<<"Hello!"<<endl;
system("pause");
return 0;
}