博主最近在练习C++相关的基础算法,前天刚把C++排序练习完,博主一共用了五种排序方式:冒泡排序、选择排序、插入排序、希尔排序和快速排序。写完后还对这五种算法面对特定情况下进行了性能比试,好了~话不多说,接下来就看看结果如何吧。
第一种、 冒泡排序
这种排序方法是最简单的排序方法也是所有初学者最熟悉的排序方法,这种方法通过一次一次的循环将循环数据中最大的数据通过比较交换到最后位置来完成排序,思路及实现办法简单但效率也是最差的。
实现代码如下:
/********************
函数名:BubbleSort
参数:Array(指针)、Size(int类型)
返回值:void
功能:冒泡排序
********************/
template void BubbleSort(T *Array,int Size)
{
for(int i = Size-1;i > 0;i--) //冒泡排序外部循环
{
for(int j = 0;j < i;j++) //冒泡排序内部循环
{
if(Array[j] > Array[j+1]) //若数组当前值比数组下一值大则交换两个数值
{
Array[j] = Array[j] + Array[j+1];
Array[j+1] = Array[j] - Array[j+1];
Array[j] = Array[j] - Array[j+1];
}
}
}
}
这种排序方法的思想是从第二个向前比较直到遇到比自己大的位置则就将该数据插入到该位置的前面,通过这样的思想以此向后走直到走到最后一个数据。这种方法在数据量较少时效率确实很高,但是当数据量十分庞大时因要进行大量的数据移动反而拖慢了其效率。
实现代码:
/**************************
函数名:InsertionSort
参数:Array(指针)、Size(int类型)
返回值:void
功能:插入排序
**************************/
template void InsertionSort(T *Array,int Size)
{
for(int i = 1;i < Size;i++) //开始循环
{
T value = Array[i]; //保存用来判断的尾值
int j;
for(j = i - 1;j >= 0;j--) //开始执行插入的中间排序
{
if(value < Array[j]) //判断前值是否大于尾值
Array[j+1] = Array[j]; //将相应的值后移
else
break;
}
Array[j+1] = value; //将尾值插入到相应的位置
}
}
这种方法先从第一个数据开始遍历找到最小的数据然后把它放到第一位然后再从第二个数据开始遍历找到次最小的数据放到第二位,以此类推完成排序,这种排序方式在博主测试的情况中是中规中矩的效率了。
实现代码如下:
/************************
函数名:SelectionSort
参数:Array(指针)、Size(int类型)
返回值:void
功能:选择排序
************************/
template void SelectionSort(T *Array,int Size)
{
int key; //定义key保存数组中最小值的下标
for(int i = 0;i < Size - 1;i++) //开始循环
{
key = i; //初始化key值
for(int j = i;j < Size;j++) //开始循环选择
{
if(Array[j] < Array[key]) //判断找到最小值
{
key = j; //将小值下标赋值给key
}
}
if(key != i) //若找到最小值则将其与初值交换
{
Array[i] = Array[i] + Array[key];
Array[key] = Array[i] - Array[key];
Array[i] = Array[i] - Array[key];
}
}
}
这种排序方式其实是插入排序的变种,插入排序中是以1为间隔向前比较排序,在希尔排序中首先将数据群分割成两个部分然后以数据群的半量为间隔进行插入排序,完成后再把数据群分割成四份然后在以四分之一为间隔进行插入排序,依次类方法进行插入排序直至间隔为1时结束这样就实现了排序。
实现代码如下:
/**********************
函数名:ShellSort
参数:Array(指针)、Size(int类型)
返回值:void
功能:Shell排序
**********************/
template void ShellSort(T *Array,int Size)
{
for(int r = (Size+1)/2;r > 0;r=(r+1)/2) //循环并计算每次中间排序的差值r
{
for(int i = r;i < Size;i++) //循环执行插入排序
{
T value = Array[i]; //保存当前尾值
int j;
for(j = i - r;j >= 0;j-=r) //按差值r循环执行插入排序
{
if(value < Array[j]) //判断当前值是否大于尾值
Array[j+r] = Array[j]; //将相应的值后移
else
break;
}
Array[j+r] = value; //将尾值插入到相应位置
}
if(r == 1) //判断结束
break;
}
}
这种排序用到了递归思想,首先先在数据群中选择一个数为标准,将比这个标准大的数据放到右侧,比这个数据小的放到左侧,然后再以这个标准数据的位置为分隔线让其左右两部分再进行一样方法的排序,直到左边界大于右边界返回。
百科上的实现方法如下:
/**********************
函数名:QuickSort
参数:Array(指针)、low(int类型)、hight(int类型)
返回值:void
功能:快速排序
**********************/
template void QuickSort(T *Array,int low,int high)
{
if(low >= high)
return;
int first = low;
int last = high;
T key = Array[first]; /*用字表的第一个记录作为枢轴*/
while(first < last)
{
while(first < last && Array[last] >= key)
--last;
Array[first] = Array[last]; /*将比第一个小的移到低端*/
while(first < last && Array[first] <= key)
++first;
Array[last] = Array[first]; /*将比第一个大的移到高端*/
}
Array[first] = key; /*枢轴记录到位*/
QuickSort(Array, low, (first-1)); //执行递归
QuickSort(Array, (first+1), high); //执行递归
}
博主是使用完全倒序的数组对其进行测试的,例如在容量为10的数组中它的内容是这样的:{10,9,8,7,6,5,4,3,2,1}.
当博主把数组容量设置为10时效果是这样的:
冒泡排序 插入排序 选择排序
希尔排序 快速排序
由上可见数据容量少的情况下快速排序的效率并没有想象中那么高。(当然这只是特殊情况下并不代表全部~ 具体情况具体分析)
当博主把数组容量设置为1000时效果是这样的:
冒泡排序 插入排序
选择排序 希尔排序
快速排序
由上可以看出在数组容量越大冒泡排序的缺点就越是明显,它所用的时间明显超过了其他排序方法很多很多,还可以看出来希尔排序明显的比其他排序快很多很多,所以在遇到这种基本上都是倒序的情况下还是比较建议使用希尔排序,这样效率可能更高些。
总结:
虽然做出了比较,但是都是在特殊情况下做出来的结果并不能代表所有,每个排序方法都有自己的特点和优点,在不同情况下适合使用不同的排序方法,当然还有堆排序和归并排序方法,博主还在研究中……… 而且这些函数博主也用模板封装起来了,可以适用在不同类型的数组排序,如果大家觉得可能有用就可以拿走用,希望对大家有用~~