前言
排序的各种算法可以说是数据结构这门学问中的精髓之一,我将会写一系列文章,为大家讲解各种排序算法的原理与实现。
一、冒泡排序
1.原理与分析
先看图:
我们看图就知道了,所谓冒泡排序就和水中的泡泡向上冒一样,越往上水的压强越小,泡泡越大。在排序中体现出来的就是将数组中的元素两两比较,比较 n 轮,升序排列则将大的数据放后面,降序排列反之。冒泡排序的理解是比较简单的,下面我们直接上代码:
2.代码实现(C#语言)
public static void BubbleSort(int[] array)
{
int temp;
for(int i = 0; i < array.Length; i++)
{
for(int j = 0; j < array.Length - 1; j++)
{
//这里是升序排列,降序排列则换成<
if(array[j] > array[j + 1])
{
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
3.优化
上述代码是冒泡排序最简易的写法,其实有几点可以优化一下。细心观察我们会发现,第一轮排序将最大的值放到了最后,所以之后的比较其实不需要再比较已经放置好的值了。另一方面,考虑到可能中途排到一半就已经是排好的顺序,之后的比较就是在浪费CPU的计算,极端情况下数组中本就是排列好的数据,那这个循环执行的毫无意义,所以我们可以在每一轮比较后判断一下,是否排好序,方法很简单,如果这一轮的比较没进行任何的位置交换,那必定是排好的顺序了,优化代码如下:
public static void BubbleSort(int[] array)
{
int temp;
bool flag;
for(int i = 0; i < array.Length; i++)
{
//每轮比较之前假设已经是排好序了
flag = true;
//已经排好序的部分就不必比较了
for(int j = 0; j < array.Length - i - 1; j++)
{
//这里是升序排列,降序排列则换成<
if(array[j] > array[j + 1])
{
//发生了位置交换,证明并没有排好序
flag = false;
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
//若排好序了,跳出循环。
if(flag)
break;
}
}
二、选择排序
1.原理与分析
先看图:
选择排序和冒泡排序都是比较好理解的初等排序算法,选择排序就是将数组分为两部分,已排序部分和未排序部分,将未排好的序列从头开始往后依次遍历,记录下最小值的索引,在一轮扫描后,若索引值发生改变,则证明未排序部分第一个索引的值不是最小值,将其与记录索引的最小值位置交换,并将交换后的位置纳入已排序部分。注意,由于这种遍历扫描,交换位置的过程,选择排序是不稳定的排序。上代码:
2.代码实现(C#)
public static void SelectionSort(int[] array)
{
int index;
int temp;
for (int i = 0; i < array.Length; i++)
{
index = i;
for (int j = i + 1; j < array.Length; j++)
{
if(array[j] < array[index])
{
index = j;
}
}
if(index != i)
{
temp = array[i];
array[i] = array[index];
array[index] = temp;
}
}
}