修炼算法内功:插入排序(二)

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个时——

同样调用后运行结果:

此时,插入排序算法的性能要比选择排序算法的要低了,花费的时间变得很大了。

从以上可以看出插入排序什么问题呢?

  • 乱序越多,耗费时间约多;
  • 乱序多,说明交换次数多;
  • 减少交换次数或则不使用交换函数就可以实现数据的移动。

在学习算法这门课程时,这些都是你我应该想到和考虑的。

不忘初心,方得始终!

猜你喜欢

转载自blog.csdn.net/Biubiuxin/article/details/81396016
今日推荐