前言
讲述部分排序算法的实现与利弊
我认为你们掌握冒泡排序,归并排序,快速排序这三种足以
冒泡排序
概念:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现他们的排序与排序要求相反时,就将他们互换。
代码实现
#include <cstdio>
int a[11] = {0,7,8,7,9,3,8,1,3,5,2};
/* 冒泡排序 */
int main()
{
int i,j;
int n = 10;
int tmp;
for(i=1;i<n;i++)
{
for(j=1;j<n;j++)
{
if(a[j] > a[j+1])//升序排序,即从小到大排序
{
tmp = a[j+1];
a[j+1] = a[j];
a[j] = tmp;
}
}
}
for(i=1;i<=10;i++)printf("%d ",a[i]);
return 0;
}
冒泡排序优缺点
优点:稳定
缺点:时间复杂度为O(n^2)
因为有两层循环,n*n
归并排序
概念:
先将整个待排序元素序列分割成若干子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序(因为直接插入排序在元素基本有序的情况下,效率很高)
这个排序算法还有一个特殊用处:求逆序对(以后再讲)
代码实现:
#include <cstdio>
#include <cstring>
int a[9] = {0,7,8,9,3,1,3,5,2};
int b[9];//用来存放某个阶段的局部的排序,然后再覆盖到a数组上
/* 归并排序 */
/*
我用|将其隔开
递归
7 8 9 3|1 3 5 2
7 8|8 3|1 3|5 2
7|8|8|3|1|3|5|2 ---->分割到最小
回溯
7 8|3 8|1 3|2 5
3 7 8 8|1 2 3 5
1 2 3 3 5 7 8 8
*/
void merge(int l,int mid,int r)
{
int ll = l;
int rr = mid+1;
int sit = l-1;
while(1)
{
if(ll > mid && rr > r)break;//要排序的数全都搞好了,退出。
if(a[ll]<a[rr])
{
if(ll <= mid)
{
b[++sit] = a[ll];
ll++;
}
else {b[++sit] = a[rr];rr++;}
}
else
{
if(rr <= r)
{
b[++sit] = a[rr];
rr++;
}
else {b[++sit] = a[ll];ll++;}
}
}
int i;
for(i=l;i<=r;i++)a[i] = b[i];//覆盖
}
void mergesort(int l,int r)
{
int mid;
if(l<r)
{
mid = (l + r) / 2;
mergesort(l,mid);//涉及递归知识
mergesort(mid+1,r);
merge(l,mid,r);//当这两边都排序完毕的时候再将这两个进行排序
}
}
int main()
{
int i,j;
int n = 10;
int tmp;
mergesort(1,8);//左端点和右端点
for(i=1;i<=8;i++)printf("%d ",a[i]);
return 0;
}
实不相瞒,这个我以前也不是很懂,就刚才写这个地方的时候查查资料自己想了想就写出来了。很简单的。
归并排序还涉及到了分治思想,能思考出来时怎么一回事吗?
对于原理不是很懂的,可以在网上找一找归并排序过程的图,再想一想。我的代码就代表了过程。
时间复杂度(nlog2n) 稳定且比冒泡快
快速排序
这是这三个之中最难理解的一个算法(个人认为)
其基本思想是:
扫描二维码关注公众号,回复:
8871218 查看本文章
1、先从数列中取出一个数作为基准数
2、分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
3、再对左右区间重复第二步,直到各区间只有一个数
代码实现
#include <cstdio>
#include <cstring>
int a[9] = {0,7,8,9,3,1,3,5,2};
/* 快速排序 */
void qsort(int l,int r)
{
int i,j;
int tmp;
if(l < r)
{
i = l;
j = r;
tmp = a[l];/*
我们取第L个数为基
准值,即这一个区间的
第一个值。可换成别的
*/
while(i < j)
{
//从右向左找第一个小于tmp的数
while(i < j && a[j] >= tmp)j--;
if(i < j)a[i++] = a[j];
//从左向右找第一个大于等于tmp的数
while(i < j && a[i] < tmp)i++;
if(i < j)a[j--] = a[i];
}
a[i] = tmp;
qsort(l,i-1);
qsort(i+1,r);
}
}
int main()
{
int i,j;
qsort(1,8);
for(i=1;i<=8;i++)printf("%d ",a[i]);
return 0;
}
总结
加强版冒泡,不稳定,极端情况下会退化成冒泡排序
说明
关于排序过程的图,网上都有,可以自己找找看看。这里不再过多叙述。