基础排序算法
本章学习并介绍三种基础排序算法,选择排序、插入排序以及希尔排序
选择排序
选择排序的思想很简单,首先从数组的第一个数开始,将第一个数与其后的所有数字比较,找到最小的一个数,放到第一个位置。然后再从数组的第二个数开始,与其后所有数字比较,找到最小的一个,放到第二个位置,以此类推……
代码如下:
void selectSort(int r[],int n) //选择排序
{
for(int i=0;i<n;++i) //第i轮比较
{
int index = i; //index指向当前这轮比较最小值
for(int j=i+1;j<n;++j)
{
if(r[index]>r[j]) //如果第j个比第index还小
{
index = j; //更新index
}
}
if(index!=i) //说明当前值要和最小值调换位置
{
int temp = r[index];
r[index] = r[i];
r[i] = temp;
}
}
}
选择排序思想很简单,所以不是重点,重点是看到一些面试会问,不通过第三个变量来交换两个变量的值,有如下三种方法:
- 加减法
a = a + b;
b = a - b;
a = a - b;
- 乘除法
a = a * b;
b = a / b;
a = a / b;
- 异或法
a ^= b; //a=a^b
b ^= a; //b=b^(a^b)=b^a^b=b^b^a=0^a=a
a ^= b; //a=(a^b)^a=a^b^a=a^a^b=0^b=b
插入排序
插入排序的基本思想是,从数组第一位开始,每次将该数字插入到前边已经排好序的子数组中,直到最后一位,则整个数组就实现了排序。
如下图所示:
代码如下:
void InsertSort(int r[],int n) //插入排序
{
for(int i=1;i<n;++i) //待插元素
{
if(r[i-1]>r[i]) //如果待插元素前一个比它大
{
int temp = r[i]; //保存待插入元素值
int j = i; //当前待插入元素即将移动到的位置
while(j>0 && r[j-1]>temp) //还需要将待插元素再往前移动
{
r[j] = r[j-1];
j--;
}
r[j] = temp; //插入
}
}
}
希尔排序
我们知道,插入排序的时间复杂度依赖于数组原始的有序性。如果数组原来就是近似有序的,插入排序的速度很快,而如果数组原来接近完全乱序或逆序,则比较慢,原因就是将待插入的元素每次向前移动一位。
因此希尔排序采用步长的概念,将数组按照一定的步长跨度分组,对每组进行插入排序,然后将步长减小,再对每组进行插入排序。这样,最后步长为1时,数组已是近似有序的,因此再使用插入排序,将提高排序的速度。
步骤如下图所示:
代码如下:
void ShellSort(int r[],int n) //希尔排序
{
for(int gap=n/2;gap>0;gap/=2) //间隔每次除以2
{
for(int i=gap;i<n;++i) //从第二组第一个数开始,形如数组[***** *****]的第5个
{
if(r[i-gap]>r[i]) //插入排序,不再详解,只是把原来的1改成现在的gap
{
int temp = r[i];
int j = i;
while(j>0 && r[j-1]>temp)
{
r[j] = r[j-gap];
j = j-gap;
}
r[j] = temp;
}
}
}
}
主函数:
int main() {
int r[] = {0,5,6,8,4,9,6,74,65,123,94};
int n = sizeof(r)/ sizeof(r[0]);
ShellSort(r,n); //可以修改排序函数
for(int i=0;i<n;i++)
{
cout<<r[i]<<" ";
}
cout<<endl;
return 0;
}