1. 对冒泡排序的理解
冒泡排序就是通过每一轮的比较,比较其相邻元素的大小,并根据比较结果,靠左元素大,则把两元素中值大的放在靠右的位置;如果靠右元素大,不进行交换
2. 对冒泡排序的示范
冒泡排序(从小到大)
第一行为数组元素
第二行为数组元素下标
示范数组:
6 5 8 9 1 3 4 7
0 1 2 3 4 5 6 7
第一步,将第0位的元素与第1位的元素比较,如果第0位的元素大于第1位,则交换元素,否则不变;将第1位的元素与第2位元素比较,如果第1位的元素大于第2位,则交换元素,否则不变;…一直到第N-2位元素与第N-1位元素比较
第一步完成后,会发现数组最末端元素第N-1位,已经变成最大值了
6 5 8 9 1 3 4 7 ===>5 6 8 9 1 3 4 7===>5 6 8 9 1 3 4 7===>5 6 8 9 1 3 4 7===>5 6 8 1 9 3 4 7===>5 6 8 1 3 9 4 7===>5 6 8 1 3 4 9 7===>5 6 8 1 3 4 7 9
第二步,同理,将第0位的元素与第1位的元素比较,如果第0位的元素大于第1位,则交换元素,否则不变;将第1位的元素与第2位元素比较,如果第1位的元素大于第2位,则交换元素,否则不变;…一直到第N-3位元素与第N-2位元素比较,完成后,不会再把第N-2位元素与第N-1位元素比较了,因为经过第一步后,第N-1位元素已经是最大值了,无需比较
第二步完成后,会发现数组次末端元素第N-2位,已经变成次大值了
5 6 8 1 3 4 7 9===>5 6 8 1 3 4 7 9===>5 6 8 1 3 4 7 9===>5 6 1 8 3 4 7 9===>5 6 1 3 8 4 7 9===>5 6 1 3 4 8 7 9===>5 6 1 3 4 7 8 9
…
一直到第N-1次,第N-1次是比较第0位元素和第1位元素比较,之后就完成了排序
3. 写程序思路
考虑使用双层循环,外层循环控制轮数,比如第一轮把数组元素的末尾元素变成最大值;第二轮把数组元素的次末尾元素变成次大值…内层循环考虑控制每一轮里具体的两两比较,但是需要注意的是越后面的轮次比较越少,比如第一轮可以一直比到末尾,而第二轮只能用次次末尾比较次末尾,而不能比较到末尾
具体实现:
外层循环:由于每一轮都会少一个元素,所以考虑使用自减,第一轮元素下标最大是N-1,故i=N-1;i>0能保证轮次,比如一个数组有3个元素,那么轮次应该是2轮,i=2,大于0,可,自减变成i=1;i=1,大于0,可,自减变成i=0;i=0,等于0,不可,于是保证了是2轮。综合起来,i=N-1;i>0;i–
内层循环:对于在外层循环的i,应该是其内层循环下标的最大值,由于是具体比较元素,次数应该是i-1次,j=0开始,j++。综合起来,j=0;j<i;j++,如果里面的str[j] > str[j + 1](j+1而不是j-1也是为了配合j<i,不然会超过i的值,会溢出数组),那么就交换
4. 程序的实现
class Program
{
static void Main(string[] args)
{
int[] t = { 3, 2, 1, 7, 8, 9, 0 };
BubbleSelection.StartBubbleSelection(t);
BubbleSelection.StartPrint(t);
Console.ReadLine();
}
}
//冒泡排序
static class BubbleSelection
{
//冒泡排序算法
public static void StartBubbleSelection(int[] str)
{
if (str == null && str.Length <= 2)
{
return;
}
for (int i = str.Length-1; i>0; i--)
{
for (int j = 0; j <i; j++)
{
if (str[j] > str[j + 1])
{
StartSwap(str, j, j + 1);
}
}
}
}
//另一种交换元素的方法,利用异或的位运算来操作,注意要保证i!=j,否则会有个值为0,
//我们调用这个方法是可以保证的,因为是str[j]和str[j+1]比较,明显下标不同
public static void StartSwap(int[] str,int i,int j)
{
str[i] = str[i] ^ str[j];
str[j] = str[i] ^ str[j];
str[i] = str[i] ^ str[j];
}
//打印数组元素
public static void StartPrint(int[] arr)
{
string t = "数组排序: ";
for (int i = 0; i < arr.Length; i++)
{
if (i == 0)
{
t = t + arr[i];
}
else
{
t = t + "-" + arr[i];
}
}
Console.WriteLine(t);
}
}
5. 时间复杂度
第一轮:比较N-1次
第二轮:比较N-2次
…
所以,加起来的比较次数是等差数列,其时间复杂度是O(N²)