基础排序算法的改进

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 https://blog.csdn.net/BaiBai_Yazi/article/details/82750390

初衷

往往基础算法的一点改进可能是前人实验很多次才钻研出来的,而对于我们自己一到需要用到一些基础常用程序段的时候,可能怎么简单就怎么来了,但是若是能好好的体会理解一下有过改进的算法,好好的记一下,这样在日常的编程中就能多多少少的提升程序性能。


原始基础算法及代码

算法使用C++数组进行实现,供参考

冒泡排序

void BubbleSort(int* arr, int n) {
	for (int i = n - 1; i > 0; i--) 
		for (int j = 0; j < i; j++)
		       if (arr[j] > arr[j + 1]) Swap(arr[j], arr[j + 1]);
	Show(arr, 20);
}

插入排序

void InsertSort(int arr[], int n) {
	for (int i = 1; i < n; i++){
		int insrt = arr[i];
		int j;
		for ( j = i; (j > 0)&&(insrt < arr[j-1]); j--) arr[j] = arr[j - 1];
		arr[j] = insrt;
	}
}

选择排序

void SelectionSort(int arr[], int n) {
	for (int i = n - 1; i >= 0; i--){
		int max = 0;
		for (int j = 1; j <= i; j++) if (arr[max] < arr[j]) max = j;
		Swap(arr[max], arr[i]);
	}
	Show(arr, 20);
}

根据名次排序

void Rearrange(int* arr,int n,int* rank) { // rank为数组中每个元素的名次
	int* temp = new int[n];
	for (int i = 0; i < n; i++) temp[rank[i]] = arr[i];
	for (int i = 0; i < n;i++) arr[i] = temp[i];
	delete []temp;
	Show(arr, 20);
}

相应的改进算法

及时终止的冒泡排序

我将冒泡算法分为了两个函数,其中Bubble函数返回一个bool值用于判断是否需要继续进行 if 比对(注意:这里我当时打了个计数器count用于观察是否减少了“交换”次数,很明显思路错误了,应该是减少的if条件语句判断的次数),及时终止体现在 bool change 的设定。若是这一轮下来都没有发生数据交换,说明一路检查过去的时候已经排序完毕。

bool Bubble(int arr[], int n) {
	bool change = false;
	for (int i = 0; i < n - 1; i++) 
		if (arr[i] > arr[i + 1]) {
			Swap(arr[i], arr[i + 1]);
			change = true;
		}
	return change;
}

void BetterBubbleSort(int arr[], int n) {
	for (int i = n; i > 1 && Bubble(arr, i,count); i--);
	Show(arr, 20);
}

及时终止的选择排序

该算法也体现在每次从一端查找到另一端,每一次的比对,都是后者大于前者 if (arr[max] <= arr[j]) max = j; else change = false; 使得change变量未被置false,从而跳出循环及时结束。

void BetterSelectionSort(int arr[], int n) {
	bool change = false;
	for (int i = n-1; (i >= 0)&&!change; i--){
		change = true;
		int max = 0;
		for (int j = 0; j <= i; j++) 
			if (arr[max] <= arr[j]) max = j;
			else change = false;
		Swap(arr[i], arr[max]);
	}
	Show(arr, 20);
}

注意:
上述两种及时终止算法(及时终止的冒泡排序,及时终止的选择排序) 对于最糟糕的情况下,相比于不及时终止算法更优,因为对额外的创建变量存在额外开销。

根据名次“原地”重组排序

“原地”重组具体体现在少了一个temp[]数组变量的创建。不要小瞧了这种对于整个数据的完全拷贝粘贴,它会在你的样本格外大的时候造成巨大额外开销。改进的原地重组算法较之前虽然运行时间相差无几,但是大幅度减少了运行时空间资源(temp[])的占用。

void BetterRearrange(int* arr, int n) {
	int* rank = new int[n];
	rank = GetRank(arr, n);
	for (int i = 0; i < n; i++) 
		while (rank[i] != i) {
			Swap(arr[i], arr[rank[i]]);
			Swap(rank[i], rank[rank[i]]);
		}
	Show(arr, 20);
	Show(rank, 20);
}

测试段代码及其运行结果

int main()
{
	clock_t start1,finish1,start2,finish2;
	double totaltime1,totaltime2;   // 计时器
	int arr[20] =   { 10,30,150,170,160,20,80,180,40,190,70,50,90,60,100,110,130,140,120,0 };									
	int arr2[20] = { 10,30,150,170,160,20,80,180,40,190,70,50,90,60,100,110,130,140,120,0 };									
	Show(arr, 20); cout << endl;
	cout << "\n程序一的运行结果为: "<< endl;
	start1 = clock();
//	此处放置运行代码1

	finish1 = clock();
	cout << endl;
	totaltime1 = (double)(finish1 - start1) / CLOCKS_PER_SEC;
	cout << "\n程序一的运行时间为" << totaltime1 << "秒!" << endl;
	
//	***********************************************

	cout << "\n程序二的运行结果为: " << endl;
	start2 = clock();
//	此处放置运行代码2

	finish2 = clock();
	totaltime2 = (double)(finish2 - start2) / CLOCKS_PER_SEC;
	cout << "\n程序二的运行时间为" << totaltime2 << "秒!" << endl;
	return 0;
}

由于数据量太小,导致无关因素对时间的影响很高,这里的简单计时仅供参考:

BettBubbleSort()与 BubbleSort();

在这里插入图片描述

BetterRearrange()与 Rearrange();

在这里插入图片描述
其他请读者您验证!
以上仅为个人学习心得与记录,感谢任何指正!

参考书:数据结构.算法与应用——C++描述 (美)Sartaj Sahni 著

猜你喜欢

转载自blog.csdn.net/BaiBai_Yazi/article/details/82750390