算法回顾(一):排序算法(上)
排序算法是最基本的算法之一,基本上所有的开发人员都接触过排序算法,所以在回顾算法时,第一个想到的就是排序算法。常见的排序算法有:
- 冒泡排序
- 选择排序
- 插入排序
- 希尔排序
- 归并排序
- 快速排序
- 堆排序
- 计数排序
- 桶排序
- 基数排序
接下了详细介绍这些算法:
冒泡排序
冒泡排序的冒泡可以很形象的表示该排序过程,简单来说,就是通过比较相邻的两个数,将较小的和较大的交换位置,这样不停的交换,最大的数就像“水泡”一样浮到最上面(数组的最后位置)。
代码如下:
void BubbleSort(int *x, int len)
{
int i = 0, j = 0;
for (i = 0; i < len-1; i++)
{
for (j = 0; j < len-i-1; j++)
{
if (x[j] > x[j+1])
{
Swap(x, j, j+1);
}
}
}
}
选择排序
选择排序就是遍历一遍数组,找到最大值所在的位置,将其与数组最后的位置进行交换,然后在剩余数组中重复此操作。
代码如下:
void SelectSort(int *x, int len)
{
int i = 0, j = 0, tmp = 0;
for (i = 0; i < len-1; i++)
{
tmp = i;
for (j = i; j < len; j++)
{
if (x[j] < x[tmp])
{
tmp = j;
}
}
Swap(x, tmp, i);
}
}
插入排序
在现实生活中,即使是没有接触过算法的人都不由自主的使用过插入排序算法,最基本的应用是:在打牌时,玩家基本都会使用插入的方式来将牌理顺,他们保持自己手牌是顺序的,然后摸到新的牌后,根据牌的大小将该牌插入到合适的位置。
假设有数组 x[n],将其升序排序。
插入排序的基本思想为:在插入新的数x[k+1]时,认为x[1…k]已经排好序了,只要将x[k+1]插入到x[1…k]中的合适位置,就可以保证x[1…k+1]是有序的。
代码如下:
void isort(int *x, int len)
{
int i = 0, j = 0;
for (i = 0; i < len; i++)
{
for (j = i; j > 0 && x[j] < x[j-1]; j--)
{
Swap(x, j, j-1);
}
}
}
可以看出插入排序的时间复杂度为O(n2),但是在数组基本为降序的情况下,插入排序的效果最差。
希尔排序
希尔排序可以被看做为插入排序的升级版,是在原始数组的不同子数组上进行排序,算法的简单步骤如下:
- 选择增量,根据增量可以将数组分割成不同子数组
- 对于每个子数组,进行排序,使用简单的排序方法,我们使用的是插入排序对于每个子数组,进行排序,使用简单的排序方法,我们使用的是插入排序
- 减小增量,重新执行以第1步,直到增量为1减小增量,重新执行以第1步,直到增量为1
代码如下:
void ShellSort(int *x, int len)
{
int step = len/2;
int i,j;
while (step >= 1)
{
for (i = step; i < len; i++)
{
for (j = i-step; j >= 0; j-=step)
{
if (x[j] > x[j+step])
{
Swap(x, j, j+step);
}
}
}
step /= 2;
}
}
归并排序
归并排序是使用递归的思想进行排序的,简单来说,就是将两个有序子序列合并成一个大的有序子序列。所以可以将归并排序简单表述为以下步骤:
- 长度为n的数组划分为n/2的子数组
- 分别对子数组进行归并排序,使其变得有序
- 将两个子数组进行合并形成一个最终的有序数组
代码如下:
//合并
void Merge(int *x, int len, int l, int h)
{
int mid = (l+h)/2;
int i = l, j = mid, k = 0;
int *tmp = new int[h-l];
while(1)
{
if (i == mid)
{
for(; j<h; j++)
{
tmp[k++] = x[j];
}
break;
}
if (j == h)
{
for(; i < mid; i++)
{
tmp[k++] = x[i];
}
break;
}
if (x[i] > x[j])
{
tmp[k++] = x[j++];
}
else
{
tmp[k++] = x[i++];
}
}
for (k=0; k<h-l; k++)
{
x[l+k] = tmp[k];
}
}
//归并排序
void MergeSort(int *x, int len, int l, int h)
{
if (h-l <= 1)
return;
int mid = (l+h)/2;
MergeSort(x, len, l, mid);
MergeSort(x, len, mid, h);
Merge(x, len, l, h);
}