冒泡排序
冒泡排序是一种理解起来较简单的排序算法,适合新手学习。
算法思路
对于一个非递增有序的数列,要将它进行递增排序,可以从第一个开始,从前至后依次将相邻两数做比较,大的数放后面,这样一次遍历比较后最大的数就被放到最后面了,然后再次从第一个数到最后第二个数同样做相邻两两比较并将大数放在后面一个,这样第二遍后整个数列第二大的数就被放在最后第二个了,这个过程是不是很像气泡冒出水面呢?O(∩_∩)O哈哈~
。一直重复这个过程,直到整个数列都有序。最糟糕的情况是原数列是递减有序的,这样n个数要做n-1遍“大数往后冒泡”的过程。
比如 原数列是 5,4,3,2,1
第一次冒泡后是 4,3,2,1,5
第二次冒泡后是 3,2,1,4,5
第三次冒泡后是 2,1,3,4,5
第四次冒泡后是 1,2,3,4,5
代码
public static void BubbleSort(int[] arr)
{
for (int i = 0; i < arr.Length - 1; i++) //控制总的冒泡次数
{
for (int j = 0; j < arr.Length - 1 - i; j++) //每次冒泡时,数组最后的i个数是数组中最大的几个数且它们几个已经递增排好,所以不用考虑它们了
{
if(arr[j]>arr[j+1])
{
//使用异或运算符来交换两个数,就不用创建中间变量
arr [j] ^= arr [j + 1];
arr [j + 1] ^= arr [j];
arr [j] ^= arr [j + 1];
}
}
}
}
优化
如果某次冒泡时未做交换,说明整个数列已经递增有序,就不需要做后面剩余的冒泡次数了,可以使用break;跳出循环。
public static void BubbleSort(int[] arr)
{
for (int i = 0; i < arr.Length - 1; i++)
{
//定义一个bool变量来标记本次冒泡过程有没有互换数据
bool exchange = false;
for (int j = 0; j < arr.Length - 1 - i; j++)
{
if(arr[j]>arr[j+1])
{
arr [j] ^= arr [j + 1];
arr [j + 1] ^= arr [j];
arr [j] ^= arr [j + 1];
exchange = true;
}
}
//如果本次冒泡没有互换数据,数列已经递增有序,使用break;结束排序
if (!exchange)
break;
}
}
选择排序
选择排序也是一种思路较简单的排序。
算法思路
对一个含n个数的非递增有序的数列进行递增排序,第一遍从数列的第1个遍历到最后一个,选出所有数中最小的一个换到第1个,然后第二遍从第2个数开始遍历,选出后面n-1个数中最小的换到第2个,以此类推,最后能将数列调整为递增有序。
比如 4,3,5,2,1
⇛
1,3,5,2,4 ⇛ 1,2,5,3,4⇛1,2,3,5,4⇛1,2,3,4,5 。
代码
public static void SellectionSort(int[] arr)
{
int pos,i,u; //pos用来记录遍历的数中最小的数的索引号
for (u = 0; u < arr.Length - 1; u++) {
pos = u; //将当前要遍历的数的第一个暂当作最小值
for (i = u; i < arr.Length; i++) {
if (arr [i] < arr [pos]) {
pos = i; //更换最小值索引记录器pos的值
}
}
if(pos != u){ //如果pos的值变换了就需要交换
//用异或来交换两个数不用定义中间变量
arr[u] ^= arr[pos];
arr[pos] ^= arr[u];
arr[u] ^= arr[pos];
}
}
}
后话
排序法 | 最差时间分析 | 平均时间复杂度 | 稳定度 | 空间复杂度 |
冒泡排序 | O(n2) | O(n2) | 稳定 | O(1) |
选择排序 | O(n2) | O(n2) | 稳定 | O(1) |