版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 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 著