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

1、最切合实际的例子

在我们生活中,常见的扑克牌就是一个很好的例子。正常人抓牌通常都是如下的几个步骤:

  1. 抓取第一张排放在手中;
  2. 抓取第二张牌与第一张做比较,如果比第一张大则放在左边,反之,右边。(放在哪边是个人习惯务必较真)
  3. 抓取第三张先与第一张比较,大左小右;再与第二张比较,大左小右。
  4. 重复抓取并循环比较,直到牌抓完。(实际人类不会每次都去一次次地去比较,再去插入)

2、插入排序

示例:5、3、1、2、4(乱序数)——>12345(有序数)

第一趟——>5作为有序数放在arr[0]——5、3、1、2、4

第二趟——>3与5比较,放在arr[0],5左移——35、1、2、4

第三趟——>1先如5比较,1与5交换;1再与3比较,1与·3交换——135、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;
}

运行结果:

结果很显然插入排序的时间远大于选择排序算法。那么能找到更加优化的插入排序算法吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值