冒泡排序是一种非常容易理解也十分简单的排序方法
其原理为:
依次比较相邻两元素的大小,若后一个元素小于前一个元素,则交换两者位置(升序),直到最后一个元素为最大元素,然后从首元素再次重复相同步骤,直到全部排序完毕
时间复杂度O(n2)
代码实现
最简单的写法是下面这种
void bubbleSort(int num[])
{
for (int i = 0; i < num.length(); i++)
{
for (int j = 0; j < num.length() - 1; j++)
{
if (num[j] > num[j + 1])//升序
{
int temp = num[j];
num[j] = num[j + 1];
num[j + 1] = temp;
}
}
}
}
我们这一段代码不难看出来,总共需要便利n次,每次便利n-1个元素,但实际上随着排序过程的进行,后面的元素都已经排序完毕的状态,是不需要每次都遍历到最后的,而且这还是最坏情况,也可能在我们进行完n次排序之前整个数组就已经排序完毕了。
因此我们可以优化一下,设置一个标志用来判断一次循环遍历后是否存在未排序的数据,同时对于已经排序的数据,我们也不再遍历
void bubbleSort(int num[], int length)
{
bool isLoop = true;//设置标志位,若一次循环中没有发生元素交换,则表示排序完毕
for (int i = 0; i < ength && isLoop; i++)
{
isLoop = false;
for(int j = 0; j < length - i - 1; j++)
{
if(num[j] > num[j + 1])//升序
{
int temp = num[j];
num[j] = num[j + 1];
num[j + 1] = temp;
isLoop = true;//发生交换表示仍存在排序过程
}
}
}
}
这样一来,效率就可大大提高
但有些时候我们可能只需要对数组中的某一段元素进行排序,而不需要排序所有的内容,所以我们可以重载一个方法
void bubbleSort(int num[], int begin, int end)
{
isLoop = true;
for(int i = end; i > begin + 1 && isLoop; i--)
{
isLoop = false;
if(int j = begin ; j < i; j++)
{
if(num[j] > num[j +1 ])]
{
int temp = num[j];
num[j] = num[j + 1];
num[j + 1] = temp;
isLoop = true;
}
}
}
}
这段代码里我们发现第一层循环的方式变了
for(int i = end; i > begin + 1 && isLoop; i--)1
我们变成了从后向前的便利方式
其实这是因为第一层循环的目的在于确定总共需要进行的遍历的次数,而他的循环方向其实无所谓,只要他所确定的循环次数正确即可,这里之所有要从后向前循环,是为了满足内层循环的要求。
我们知道,内层循环的循环终点随着外层循环的进行每都会自减,这是为了提高效率,因为每一次完全遍历都会有一个元素被排到后面,也就是说从尾部开始向前的 i 个元素都是排好序的,所以我们内层就不需要再次遍历他们,但是这是建立在 i 是从零开始计数的基础上的。如果我们指定排序的开始和结束位置,就不能用以前的方法,因为 i 不是从零开始的,以 i 做为已排好序的元素个数自然是不对的,所以我们令 i 从指定元素段的尾部开始向前,每次遍历拍好一个元素,i 所指示的尾部位置便前移一位,这样就可以直接利用 i 来作为内层循环的终止条件了