5、插入算法的改进
在前面说到的插入排序算法中我们用到了比较和交换,对于完全乱序的数组,上述算法的性能是比选择排序的算法还要差很多。原因就是进行了swap()函数操作,也就是三次赋值操作。
如果我们想优化算法,我们应该从那方面去优化呢?
代码如下:
//优化后的插入排序
template<typename T>
void BetterInsertionSort(T arr[], int n)
{
if (arr == NULL)
return;
for (int i = 1;i < n;i++)//逐一访问数组元素
{
T temp = arr[i];//创建辅助变量,保存当前arr[i]数据,然后与[0,i-1)去逐一比较
int j;//用来保存元素temp应该插入的位置
for (j = i;j > 0 && arr[j - 1] > temp;j--)//比较arr[i]与arr[0]...arr[i-1]的大小,并返回插入的位置
{
arr[j] = arr[j - 1];//将比arr[i]大的数复制给arr[i],j继续左移去比较
}
arr[j] = temp;//由上述循环返回插入位置,temp插入进去
}
}
主函数调用:
int main() {
int n = 10000;
int* arr1 = SortTestHelper::generateRandomArray(n, 0, n);//随机生成数组arr1
int* arr2 = SortTestHelper::copyIntArray(arr1, n);//复制数组arr1中的数据,生成与arr1完全一样的数组arr2
int* arr3 = SortTestHelper::copyIntArray(arr1, n);//复制数组arr1中的数据,生成与arr1完全一样的数组arr3
SortTestHelper::SortTimeTest("Insertion Sort", insertionSort, arr1, n);//测试插入排序算法性能
SortTestHelper::SortTimeTest("BetterInsertion Sort", BetterInsertionSort, arr2, n);//测试插入排序算法性能
SortTestHelper::SortTimeTest("Selection Sort", selectionSort, arr3, n);//测试选择排序算法性能
delete[] arr1;
delete[] arr2;
delete[] arr3;
system("pause");
return 0;
}
运行结果:
很显然,优化后的排序算法要比之前的插入算法的性能要更加优化,所用时间更少。
6、插入排序一个小测试——比较10000组数内完全乱序和几乎有序的性能
(1)、添加几乎有序数组的生成函数
//生成近乎有序随机数组
int *generateNearlyOrderedArray(int n, int swapTimes)
{
int *arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = i;
}//先生成完全有序数组
srand(time(NULL));
for (int i = 0; i < swapTimes; i++)//随后设置乱序个数swapTimes
{
int posx = rand() % n;
int posy = rand() % n;
swap(arr[posx],arr[posy]);
}
return arr;
}
数组中乱序数位10个时——
主函数调用:
int main() {
int n=10000;
int* arr1 = SortTestHelper::generateNearlyOrderedArray(n,10);//随机生成数组arr1,10000个数里仅有10个乱序
int* arr2 = SortTestHelper::copyIntArray(arr1,n);//复制数组arr1中的数据,生成与arr1完全一样的数组arr2
int* arr3 = SortTestHelper::copyIntArray(arr1,n);//同样复制一份数组arr3测试
SortTestHelper::timeTestSort("Insertion Sort",insertionSort,arr1,n);//测试插入排序算法性能
SortTestHelper::timeTestSort("Selection Sort",selectionSort,arr2,n);//测试选择排序算法性能
SortTestHelper::timeTestSort("BetterInsertion Sort",BetterInsertionSort,arr3,n);//测试优化后插入排序算法性能
delete[] arr1;
delete[] arr2;
delete[] arr3;
system("pause");
return 0;
}
运行结果:
此时,插入排序的性能是比选择排序的算法优越的。
数组中乱序数位100个时——
同样调用后运行结果:
数组中乱序数位1000个时——
同样调用后运行结果:
此时,插入排序算法的性能要比选择排序算法的要低了,花费的时间变得很大了。
从以上可以看出插入排序什么问题呢?
- 乱序越多,耗费时间约多;
- 乱序多,说明交换次数多;
- 减少交换次数或则不使用交换函数就可以实现数据的移动。
在学习算法这门课程时,这些都是你我应该想到和考虑的。
不忘初心,方得始终!