- 目的
进行希尔排序练习。明白希尔排序原理。
希尔排序:将间隔d的元素视为待排序数组,对该数组进行插入排序。然后逐步缩小d的值,最后直到d=1。这个特点又可以称呼希尔排序为缩小增量排序。
d=1时为直接插入排序。
d值的取法一般为折半获取,即每次排序完成,d=d/2。初始d=n/2。 - 代码
实现代码:
void ShellSort(T testArray[], int nSize){
LogInfo<T> log = LogInfo<T>();
T key;//哨兵值
int times(0), i(0),j(0),d(0),k(0), compare(0), move(0);//记录遍历次数,比较次数,移动次数
log.ShowState("原始数组为 :");
log.ShowArray(testArray, nSize);
//折半d,d为偶数,则加1,排除0
//d = nSize / 2;
//d=d != 0 && d % 2 == 0 ? d + 1 : d;
//for (d; d >=1; d=d/2,d=d!=0&&d%2==0?d+1:d){
for (d = nSize / 2; d >= 1;d=d/2){
compare++;
times++;
for (k = 0; k < d; k++)
{
//以d间隔的第一轮排序
for (i = k+d; i < nSize; i = i + d){
if (testArray[i] < testArray[i - d]){
key = testArray[i];//记录待排元素作为哨兵
for (j = i - d; j >= 0 && key < testArray[j]; j = j - d){
compare++;
testArray[j + d] = testArray[j];
move++;
}
testArray[j + d] = key;
move++;
}
}
}
log.ShowState("第", times, "趟数组为:");
log.ShowArray(testArray, nSize);
}
log.ShowState("最终数组为 :");
log.ShowArray(testArray, nSize);
log.ShowState("比较次数:", compare);
log.ShowState(" 移动次数:", compare);
log.ShowLine();
};
测试代码:
#include<iostream>
#include"Test.h"
#include"Sort.h"
#define N_MAX 7
int main()
{
using namespace Test;
using namespace MyAlgorithm;
using namespace std;
LogInfo<double> log = LogInfo<double>();
Sort<double> sortTest = Sort<double>();
log.ShowState("测试希尔排序");
log.ShowLine();
log.ShowState("测试正序数组========================");
log.ShowLine();
TestDataCreator<double, N_MAX> testArray = TestDataCreator<double, N_MAX>(PositiveArray);
sortTest.ShellSort(testArray.GetArray(), testArray.GetSize());
log.ShowState("测试降序数组========================");
log.ShowLine();
testArray = TestDataCreator<double, N_MAX>(NegativeArray);
sortTest.ShellSort(testArray.GetArray(), testArray.GetSize());
log.ShowState("测试随机数组========================");
log.ShowLine();
testArray = TestDataCreator<double, N_MAX>(RandomArray);
sortTest.ShellSort(testArray.GetArray(), testArray.GetSize());
int nWait;
cin >> nWait;
return 0;
}
输出结果截图:
- 遇到难题
1)网络上算法看了很难懂,但是比较简洁,没有仔细深究,最后仔细研究才明白希尔算法原理。代码尽管不简洁但是很能表述算法原理。
2)希尔算法的证明,没有查询到相关资料,起初无法证明,后来自思考,不管希尔排序怎么排序,最终都有d=1这个步骤,这个步骤是直接插入排序,因此该算法正确。根本不需要证明希尔算法,只需证明希尔算法的优点,这个优点只能从定性上表述,以及实际测试表明。数学证明比较困难,自己知识不足。 - 经验
1)希尔排序有点是移动次数相对较少,为什么会这样,有一种无序命中的感觉吧。在有序的世界里,你总是从一个列表中一一去寻找,挪动。无序的世界里,希尔排序增大了一种可能性,这个元素恰好在这个位置上的概率。
2)该排序算法时间复杂度为O(n^s) s(1,2),平均复杂度为nlogn。不稳定。空间复杂度O(1)。
3)算法优点:算法较简单,代码短,需要的空间小,速度还可以,适合情况复杂的排序,适合中小规模的排序
算法缺点:速度偏慢,不够智能,不适合情况简单的排序,不适合大规模排序。 - 后续
1)进行选择排序练习。
2)分析网络上流行的希尔排序。该任务暂时搁置,放在所有种类排序算法之后进行。