1、最切合实际的例子
在我们生活中,常见的扑克牌就是一个很好的例子。正常人抓牌通常都是如下的几个步骤:
- 抓取第一张排放在手中;
- 抓取第二张牌与第一张做比较,如果比第一张大则放在左边,反之,右边。(放在哪边是个人习惯务必较真)
- 抓取第三张先与第一张比较,大左小右;再与第二张比较,大左小右。
- 重复抓取并循环比较,直到牌抓完。(实际人类不会每次都去一次次地去比较,再去插入)
2、插入排序
示例:5、3、1、2、4(乱序数)——>1、2、3、4、5(有序数)
第一趟——>5作为有序数放在arr[0]——5、3、1、2、4
第二趟——>3与5比较,放在arr[0],5左移——3、5、1、2、4
第三趟——>1先如5比较,1与5交换;1再与3比较,1与·3交换——1、3、5、2、4
第四趟——>2先与5比较,2与5交换;2与3比较,2与3交换;2与1比较,不必交换——1、2、3、5、4
第五趟——>4先与5比较,4与5交换;4再与3比较,不必交换;比较停止——1、2、3、4、5
3、算法分析
代码块:
template<typename T>
void insertionSort(T arr[],int n) {
if (arr == NULL)
return;
for (int i = 1; i < n;i++) {
//寻找元素arr[]合适的插入位置
for (int j = i; j > 0;j--) {//从当前元素开始比较,一直到arr[0]位置元素为比较完成
if (arr[j] < arr[j - 1])//如果后面元素大于前面就会交换
swap(arr[j], arr[j - 1]);
else
break;
}
}
}
4、性能测试(函数写在SortTestHelper.h头文件中,作为自定义函数调用)
(1)、函数时间的测试
//函数时间测试
template<typename T>
void timeTestSort(string sortName, void(*sort)(T[], int), T arr[], int n)
{
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
assert(isSorted(arr, n));//放在测试时间函数之后,此程序也会占用测试时间,使测试结果不正确。
cout << sortName << ":" << double(endTime - startTime)
/ CLOCKS_PER_SEC << "s" << endl;
return;
}
(2)、验证函数排序的正确性
//验证函数排序的正确性
template<typename T>
bool isSorted(T arr[], int n)
{
for (int i = 0; i < n - 1; i++) {
if (arr[i] > arr[i + 1])
return false;
}
return true;
}
(3)、函数的复制
//函数的复制
int* copyIntArray(int a[],int n)
{
int* arr = new int[n];
copy(a,a+n,arr);
return arr;
}
};
主函数调用
int main() {
int n=10000;
int* arr1= SortTestHelper::generateRandomArray(n,0,n);//随机生成数组arr1
int* arr2 = SortTestHelper::copyIntArray(arr1,n);//复制数组arr1中的数据,生成与arr1完全一样的数组arr2
SortTestHelper::timeTestSort("Insertion Sort",insertionSort,arr1,n);//测试插入排序算法性能
SortTestHelper::timeTestSort("Selection Sort",selectionSort,arr2,n);//测试选择排序算法性能
delete[] arr1;
delete[] arr2;
system("pause");
return 0;
}
运行结果:
结果很显然插入排序的时间远大于选择排序算法。那么能找到更加优化的插入排序算法吗?