排序(二)__冒泡排序、简单选择排序和直接插入排序

前面《排序(一)__综述》提到按照算法的复杂度分为简单算法和改进算法两大类,本文主要就简单算法中的冒泡排序、简单选择排序和直接插入排序进行通俗详细的解析。


一、冒泡排序

1、基本概念
冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。(动态图来自维基百科)
排序(二)__冒泡排序、简单选择排序和直接插入排序_第1张图片

2、关键代码(优化之后)
void BubbleSort(SqList *L)
{
int i,j;
Status flag=TRUE;            //flag用作标记,避免已经有序的情况下无意义的循环判断
for(i=1;ilength&&flag;i++)//若flag为true则退出循环
{
flag=FALSE;               //初始为false
for(j=L->length-1;j>=i;j--)//j从后往前循环
{
if(L->r[j]>L->r[j+1])
{
swap(L,j,j+1);     //交换L->r[j]和L->r[j+1]的值
flag=TRUE;         //如果有数据交换则为true
}

}
}
}
3、复杂度分析
总的时间复杂度为o(n^2)


二、简单选择排序

1、通俗解释

案例一 对比 案例二
爱炒股票短线,不断买进卖出,想通过差价来实现盈利。但通常频繁操作的人,即使失误不多,也会因为操作的手续费和印花税过高而获利很少。 VS 另一种做股票的人,他们很少出手,只是在不断的观察和判断,等到时机一到果断买进或卖出。
冒泡排序的思想就是不断的进行交换,通过交换完成最终的排序,这和上面一种做股票频繁操作的人类似 VS 案例二中的股票高手一样,排序时找到合适的关键字再做交换并且只移动一次完成相应关键字的排序定位工作,这就是选择排序的基本思想

2、基本定义

简单选择排序法(Simple Selection Sort)就是通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换。

排序(二)__冒泡排序、简单选择排序和直接插入排序_第2张图片


它的工作原理如下:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

3、关键代码

void SelectSort(SqList *L)

{

int i,j,min;

for(i=1;ilength;i++)

{

min=i;//将当前下标定义为最小值下标

for(j=i+1;j<=L->length;j++)//循环之后的数据

{

if(L->r[min]>L->r[j])//如果有小于当前最小值得关键字

min=j;//将关键字下标赋值给min

}

if(i!=min)//若min不等于i说明找到最小值交换

swap(L,i,min);

}


}

4、复杂度分析

总的时间复杂度为o(n^2)


三、直接插入排序

1、引入
扑克玩法就是一边摸牌,一边理牌。一副打乱的同花顺理牌过程就是直接插入排序法。
2、基本概念
基本插入排序的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。
排序(二)__冒泡排序、简单选择排序和直接插入排序_第3张图片

它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
3、关键代码
void InsertSort(SqList *L)
{
int i,j;
for(i=2;i<=L->length;i++)//i从2开始假设已放好位置,后面的牌其实就是插入到它左右侧
{
if(L->r[i]r[i-1])//需要将L->r[i]插入有序表
{
L->r[0]=L->r[i];//设置哨兵 循环终止的判断依据
for(j=i-1;L->r[j]>L->r[0];j--)
L->r[j+1]=L->r[j];//记录后移
L->r[j+1]=L->r[0];//插入到正确位置
}
}
}

4、复杂度分析

时间复杂度为O(n^2)



最后说明:尽管冒泡排序、简单选择排序、直接插入排序的时间复杂度均为O(n^2),但就性能方面有如下特点直接插入排序>简单选择排序>冒泡排序








你可能感兴趣的:(【数据结构与算法】)